AOP(Aspect Orient Programming),一般稱為面向方面(切面)編程,作為面向對象的一種補充,
我們將業務處理的主要流程是作為核心關注點,而用於處理系統中分布於各個模塊中與核心業務無關的, 比如事務管理、日志、緩存等等,稱為橫切關注點,AOP的作用就是將核心關注點和橫切關注點分離開來。
AOP核心概念
1、切入點(pointcut)
需要要增強的目標方法,比如:你的一個類有很多方法,但是只需要在login方法執行記錄一下日志,其他的方法不需要,那么這login方法就是一個切點
2、連接點(joinpoint)
這里指的是方法連接點,連接點可以說是切點的全集。方法有關的前前后后都是連接點。
3、通知(advice)
某個方法在執行前或執行后需要完成的工作,比如在某個方法執行完成后記錄一下日志。在什么時候和要完成什么通過方法名中的before,after,around等來實現
4、切面(aspect)
切面是通知和切點的結合,切點和通知共同定義了切面的全部功能——它是什么,在何時何處完成其功能 , 切面就是對橫切關注點的抽象
AOP實現的關鍵在於AOP框架自動創建的AOP代理,
AOP代理主要分為靜態代理和動態代理,靜態代理的代表為AspectJ;而動態代理則以Spring AOP為代表
Spring AOP使用的動態代理,所謂的動態代理就是說AOP框架不會去修改原來原來的對象,而是在需要的時候重新生成一個代理對象,這個代理對象包含了目標對象的全部方法,並且在指定的切點做了了處理,而且最終還是回調原對象的方法。
動態代理主要有兩種方式,JDK動態代理和CGLIB動態代理。JDK動態代理通過反射來接收被代理的類,並且要求被代理的類必須實現一個接口。JDK動態代理的核心是InvocationHandler接口和Proxy類。
如果目標類沒有實現接口,那就要選擇使用CGLIB來動態代理目標類。
CGLIB會讓生成的代理類繼承當前對象,並在代理類中對代理方法進行強化處理(前置處理、后置處理等)。
在CGLIB底層底層實現是通過ASM字節碼處理框架來轉換字節碼並生成新的代理類
注意,CGLIB是通過繼承的方式做的動態代理,因此如果某個類被標記為final,那么它是無法使用CGLIB做動態代理的。
在Spring Aop框架中,MethodInterceptor接口被用來攔截指定的方法,對方法進行增強。
在Aop中每個advistor 里面會有一個advice具體做切面動作,Spring提供了AspectJAfterReturningAdvice,AspectJMethodBeforeAdvice,AspectJAroundAdvice,AspectJAfterAdvice這幾個advice,在XML 配置aop時候會指定<aop:after-returning/>,<aop:before/>,<aop:around/>,<aop:after/>
,其實內部就是創建上面對應的這些advice。
從圖知道AspectJAfterReturningAdvice和AspectJMethodBeforeAdvice沒有實現MethodInterceptor接口,其他兩者則實現了該接口。
而Spring Aop的方法攔截器卻必須是實現了MethodInterceptor的,所以Spring提供了對應的適配器來適配這個問題,分別是MethodBeforeAdviceAdapter和AfterReturningAdviceAdapter和ThrowsAdviceAdapter。
適配器模式屬於結構性模式,它為兩個不同接口之間互通提供了一種手段。
下面是 DefaultAdvisorAdapterRegistry類的全部代碼, 會默認注冊 上面三個適配器,
public class DefaultAdvisorAdapterRegistry implements AdvisorAdapterRegistry, Serializable { private final List<AdvisorAdapter> adapters = new ArrayList<AdvisorAdapter>(3); /** * Create a new DefaultAdvisorAdapterRegistry, registering well-known adapters. */
public DefaultAdvisorAdapterRegistry() { registerAdvisorAdapter(new MethodBeforeAdviceAdapter()); registerAdvisorAdapter(new AfterReturningAdviceAdapter()); registerAdvisorAdapter(new ThrowsAdviceAdapter()); } @Override public Advisor wrap(Object adviceObject) throws UnknownAdviceTypeException { if (adviceObject instanceof Advisor) { return (Advisor) adviceObject; } if (!(adviceObject instanceof Advice)) { throw new UnknownAdviceTypeException(adviceObject); } Advice advice = (Advice) adviceObject; if (advice instanceof MethodInterceptor) { // So well-known it doesn't even need an adapter.
return new DefaultPointcutAdvisor(advice); } for (AdvisorAdapter adapter : this.adapters) { // Check that it is supported.
if (adapter.supportsAdvice(advice)) { return new DefaultPointcutAdvisor(advice); } } throw new UnknownAdviceTypeException(advice); } @Override public MethodInterceptor[] getInterceptors(Advisor advisor) throws UnknownAdviceTypeException { List<MethodInterceptor> interceptors = new ArrayList<MethodInterceptor>(3); Advice advice = advisor.getAdvice(); if (advice instanceof MethodInterceptor) { interceptors.add((MethodInterceptor) advice); } for (AdvisorAdapter adapter : this.adapters) { if (adapter.supportsAdvice(advice)) { interceptors.add(adapter.getInterceptor(advisor)); } } if (interceptors.isEmpty()) { throw new UnknownAdviceTypeException(advisor.getAdvice()); } return interceptors.toArray(new MethodInterceptor[interceptors.size()]); } @Override public void registerAdvisorAdapter(AdvisorAdapter adapter) { this.adapters.add(adapter); } }
以MethodBeforeAdviceAdapter為例子看下:
class MethodBeforeAdviceAdapter implements AdvisorAdapter, Serializable { @Override public boolean supportsAdvice(Advice advice) { return (advice instanceof MethodBeforeAdvice); } @Override public MethodInterceptor getInterceptor(Advisor advisor) { MethodBeforeAdvice advice = (MethodBeforeAdvice) advisor.getAdvice(); return new MethodBeforeAdviceInterceptor(advice); } }
MethodBeforeAdviceInterceptor的代碼如下:
public class MethodBeforeAdviceInterceptor implements MethodInterceptor, Serializable { private MethodBeforeAdvice advice; /** * Create a new MethodBeforeAdviceInterceptor for the given advice. * @param advice the MethodBeforeAdvice to wrap */
public MethodBeforeAdviceInterceptor(MethodBeforeAdvice advice) { Assert.notNull(advice, "Advice must not be null"); this.advice = advice; } @Override public Object invoke(MethodInvocation mi) throws Throwable { this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis() ); return mi.proceed(); } }
可知MethodBeforeAdviceInterceptor繼承了MethodInterceptor作為了一個適配器內部委托請求給MethodBeforeAdvice。