【JAVA筆記——器】Spring面向切面編程 Aspect Oriented Programming with Spring

並非完全按照Reference翻譯,有刪改
原文 Aspect Oriented Programming with Spring

AOP術語

通知Advice
切面的工作爲通知
SPRING 五種通知
before after after-returning after-throwing around

連接點 Joinpoint
連接點是執行過程中能夠插入切面的一個點

切點 Pointcut
並非所有連接點都需要被通知,切點定義匹配通知所要織入的一個多或多個連接點

切面 Aspect
切面是通知和切點的結合。定義切面的如何實現

引入 Inteoduction
引入允許我們向現有的類添加新方法或屬性

織入 Weaving
織入是將切面應用到目標對象創建新的代理對象的過程。切面在指定的連接點被織入到目標對象中。目標對象的生命週期有多個點可以織入

  • 編譯期
  • 類加載期
  • 運行期

配置

@Aspect

Aspect註解切面對象

package org.xyz;
import org.aspectj.lang.annotation.Aspect;

@Aspect
public class NotVeryUsefulAspect {

}

切點

AspectJ包含的不支持
call, get, set, preinitialization, staticinitialization, initialization, handler, adviceexecution, withincode, cflow, cflowbelow, if, @this, and @withincode
使用報出IllegalArgumentException

execution - 連接點匹配方法,這是在Sring AOP主要的使用的切點設計器
within - 限制匹配連接點在特定類型,相當於簡化的execution方法
this - 限制匹配連接點所對應Bean引用是特定類型
args - 限制匹配連接點的參數列表是特定類型
@target - 限制匹配連接點對應的類的對象擁有所標記的的類型
@args - 限制匹配連接點對應的類運行時參數是所標記的類型
@within - 限制匹配連接點在標註的類中
@annotation - 限制匹配連接點,連接點的主體被註解

execution - for matching method execution join points, this is the primary pointcut designator you will use when working with Spring AOP

within - limits matching to join points within certain types (simply the execution of a method declared within a matching type when using Spring AOP)

this - limits matching to join points (the execution of methods when using Spring AOP) where the bean reference (Spring AOP proxy) is an instance of the given type

target - limits matching to join points (the execution of methods when using Spring AOP) where the target object (application object being proxied) is an instance of the given type

args - limits matching to join points (the execution of methods when using Spring AOP) where the arguments are instances of the given types

@target - limits matching to join points (the execution of methods when using Spring AOP) where the class of the executing object has an annotation of the given type

@args - limits matching to join points (the execution of methods when using Spring AOP) where the runtime type of the actual arguments passed have annotations of the given type(s)

@within - limits matching to join points within types that have the given annotation (the execution of methods declared in types with the given annotation when using Spring AOP)

@annotation - limits matching to join points where the subject of the join point (method being executed in Spring AOP) has the given annotation

原生Spring AOP基於代理(無論是JDK Proxy/CGLIB),均無法對可訪問性小於protected的類進行代理。
如果需要,可以使用Spring-driven native AspectJ weaving

Spring AOP支持PCD命名Bean,idOrNameOfBean支持* , &&, ||

bean(idOrNameOfBean)

Demo

@Pointcut("execution(public * *(..))")
private void anyPublicOperation() {}

@Pointcut("within(com.xyz.someapp.trading..*)")
private void inTrading() {}

@Pointcut("anyPublicOperation() && inTrading()")
private void tradingOperation() {}

官方提供公共配置

package com.xyz.someapp;

import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;

@Aspect
public class SystemArchitecture {

    /**
     * A join point is in the web layer if the method is defined
     * in a type in the com.xyz.someapp.web package or any sub-package
     * under that.
     */
    @Pointcut("within(com.xyz.someapp.web..*)")
    public void inWebLayer() {}

    /**
     * A join point is in the service layer if the method is defined
     * in a type in the com.xyz.someapp.service package or any sub-package
     * under that.
     */
    @Pointcut("within(com.xyz.someapp.service..*)")
    public void inServiceLayer() {}

    /**
     * A join point is in the data access layer if the method is defined
     * in a type in the com.xyz.someapp.dao package or any sub-package
     * under that.
     */
    @Pointcut("within(com.xyz.someapp.dao..*)")
    public void inDataAccessLayer() {}

    /**
     * A business service is the execution of any method defined on a service
     * interface. This definition assumes that interfaces are placed in the
     * "service" package, and that implementation types are in sub-packages.
     *
     * If you group service interfaces by functional area (for example,
     * in packages com.xyz.someapp.abc.service and com.xyz.someapp.def.service) then
     * the pointcut expression "execution(* com.xyz.someapp..service.*.*(..))"
     * could be used instead.
     *
     * Alternatively, you can write the expression using the 'bean'
     * PCD, like so "bean(*Service)". (This assumes that you have
     * named your Spring service beans in a consistent fashion.)
     */
    @Pointcut("execution(* com.xyz.someapp..service.*.*(..))")
    public void businessService() {}

    /**
     * A data access operation is the execution of any method defined on a
     * dao interface. This definition assumes that interfaces are placed in the
     * "dao" package, and that implementation types are in sub-packages.
     */
    @Pointcut("execution(* com.xyz.someapp.dao.*.*(..))")
    public void dataAccessOperation() {}

}

匹配規則

execution(modifiers-pattern? ret-type-pattern declaring-type-pattern?name-pattern(param-pattern) throws-pattern?)

ret-type-pattern | name-pattern | param-pattern必選,其他可選

modifiers-pattern 修飾語匹配 : public *匹配任意類型
ret-type-pattern 返回類型匹配 : Object *匹配任意類型
declaring-type-pattern 定義類型匹配 : com.cunchen.entity.Test *匹配任意類型
name-pattern 方法名匹配 : testMethod *匹配任意方法
param-pattern 參數匹配 : Object | ()無參數 | (..)任意參數 | ()任意一個參數 | ( , String) 任意一個參數 + 一個String參數

//匹配public方法
execution(public * *(..))

//匹配開始名稱set
execution(* set*(..))

//匹配AccountService的子類實現方法
execution(* com.xyz.service.AccountService.*(..))

//匹配com.xyz.servic包下接口的子類實現方法
execution(* com.xyz.service.*.*(..))

//在com.xyz.service包中的任意連接點
within(com.xyz.service.*)

//在com.xyz.service包以及子包中的任意連接點
within(com.xyz.service..*)

//代理接口AccountService的任意連接點
this(com.xyz.service.AccountService)

//任意實現AccountService接口實現對象的連接點
target(com.xyz.service.AccountService)

//任意只有一個參數,且參數在運行時是Serializable的任意連接點
args(java.io.Serializable)

//任意目標對象被註解爲@Transactional的連接點
@target(org.springframework.transaction.annotation.Transactional)

//任意目標對象的聲明中擁有@Transactional
@within(org.springframework.transaction.annotation.Transactional)

//任意連接點被註釋@Transactional
@annotation(org.springframework.transaction.annotation.Transactional)

//任意連接點,它接受一個參數,並且傳入的參數的運行時類型有@Classified註解
@args(com.xyz.security.Classified)

//任意 Spring bean 命名爲 tradeService 的連接點
bean(tradeService)

//任意 Spring bean 符合通配符統配爲 *Service 的連接點
bean(*Service)
發佈了69 篇原創文章 · 獲贊 51 · 訪問量 13萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章