Advice
通知:
-
BeforeAdvice
:接口MethodBeforeAdvice
侨糟,方法before()
-
AfterAdvice
:接口AfterReturningAdvice
碍扔,方法afterReturning()
-
ThrowsAdvice
:在拋出異常時回調(diào),這個回調(diào)是AOP通過反射機制完成的秕重。
Pointcut
切點:
概念:決定Advice
通知應該作用于哪個連接點不同。返回一個MethodMatcher
,由它來判斷是否需要對當前方法調(diào)用進行增強溶耘,或者是否需要對當前調(diào)用方法應用配置好的Advice
通知二拐。
- 通過正則表達式進行匹配
- 通過方法名進行匹配
- 等等
Spring AOP的設計和實現(xiàn)
JVM動態(tài)代理
Advisor通知器:
概念:將Advice
和pointcut
結合起來,可以定義應該使用哪個通知在哪個關注點使用凳兵。
建立AopProxy代理對象
ProxyFactoryBean:封裝了主要代理對象的生成過程百新,生成方式有兩種
- JDK的Proxy
-
CGLIB
這里寫圖片描述
JDK生成AopProxy
代理對象
public Obejct getObject(ClassLoader classLoader) {
if (logger.isDebugEnabled()) {
logger.debug("Creating JDK dynamic proxy: target source is " + this.advised.getTargetSource());
}
Class[] proxiedInterfaces AopProxyUtils.completeProxiedInterfaces(this.advised);
findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
//這是調(diào)用JDK生成Proxy的地方
return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
}
攔截器調(diào)用的實現(xiàn)
JdkDynamicAopProxy
的invoke
攔截:
當Proxy對象的代理方法被調(diào)用的時候,JdkDynamicAopProxy
的invoke
方法作為Proxy對象的回調(diào)函數(shù)被觸發(fā)庐扫,從而通過invoke的具體實現(xiàn)饭望,構造ReflectiveMethodInvocation
對象來完成對目標對象方法調(diào)用的攔截或者說功能增強仗哨。
Cglib2AopProxy
的intercept
攔截:
與JdkDynamicAopProxy
的回調(diào)實現(xiàn)非常類似,唯一不同的是構造CglibMethodInvocation
對象來完成攔截器鏈的調(diào)用铅辞。
對目標方法的調(diào)用:
- jdk:使用反射機制得到調(diào)用方法的反射對象厌漂,然后使用invoke啟動對方法反射對象的調(diào)用。
- cglib:通過
MethodProxy
對象來直接invoke完成的
AOP攔截器鏈的調(diào)用:
1. 先進行判斷斟珊,如果已經(jīng)運行到攔截器鏈的末尾苇倡,直接調(diào)用目標對象的實現(xiàn)方法
2. 否則,沿著攔截器鏈繼續(xù)進行囤踩,得到下一個攔截器旨椒,通過這個攔截器進行matches
判斷,是否適用于橫切增強的場合高职,如果是钩乍,從攔截器中得到通知器,并啟動通知器的invoke
方法進行切面增強
3. 結束之后怔锌,迭代調(diào)用proceed
方法寥粹,直到攔截器鏈中的攔截器都完成以上的攔截過程為止
配置通知器:
MethodBeforeAdviceAdapter
的實現(xiàn)
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
的實現(xiàn)
public class MethodBeforeAdviceInterceptor implements MethodInterceptor, Serializable {
private MethodBeforeAdvice advice;
//為指定的Advice創(chuàng)建對應的MethodBeforeAdviceInterceptor對象
public MethodBeforeAdviceInterceptor(MethodBeforeAdvice advice) {
Assert.notNull(advice, "Advice must not be null");
this.advice = advice;
}
//這個invoke方法是攔截器的回調(diào)方法,會在代理對象的方法被調(diào)用時觸發(fā)回調(diào)
@Override
public Object invoke(MethodInvocation mi) throws Throwable {
this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis() );
return mi.proceed();
}
}
AfterReturningAdviceInterceptor
的實現(xiàn)
public class AfterReturningAdviceInterceptor implements MethodInterceptor, AfterAdvice, Serializable {
private final AfterReturningAdvice advice;
/**
* Create a new AfterReturningAdviceInterceptor for the given advice.
* @param advice the AfterReturningAdvice to wrap
*/
public AfterReturningAdviceInterceptor(AfterReturningAdvice advice) {
Assert.notNull(advice, "Advice must not be null");
this.advice = advice;
}
@Override
public Object invoke(MethodInvocation mi) throws Throwable {
Object retVal = mi.proceed();
this.advice.afterReturning(retVal, mi.getMethod(), mi.getArguments(), mi.getThis());
return retVal;
}
}
Spring AOP的高級特性
HotSwappableTaregetSource
:使用戶可以以線程安全的方式切換目標對象埃元,提供所謂的熱交換功能涝涤。
public synchronized Object swap(Object newTarget) throws IllegalArgumentException {
Assert.notNull(newTarget, "Target object must not be null");
Object old = this.target;
this.target = newTarget;
return old;
}
public synchronized Object getTarget() {
return this.target;
}