1.類繼承結(jié)構(gòu)
2.解析
AdvisedSupport繼承ProxyConfig,自身提供了以下功能
- 配置當(dāng)前代理的Adivsiors
- 配置當(dāng)前代理的目標(biāo)對象
- 配置當(dāng)前代理的接口
- 提供getInterceptorsAndDynamicInterceptionAdvice方法用來獲取對應(yīng)代理方法對應(yīng)有效的攔截器鏈
AdvisedSupport本身不會提供創(chuàng)建代理的任何方法,專注于生成攔截器鏈
我們來探究下第4點中的攔截器是什么東西介蛉,以及getInterceptorsAndDynamicInterceptionAdvice的源碼實現(xiàn)
先看下攔截器(MethodInterceptor)的接口定義
public interface MethodInterceptor extends Interceptor {
Object invoke(MethodInvocation invocation) throws Throwable;
}
攔截器的作用是封裝在目標(biāo)方法前后執(zhí)行相應(yīng)的邏輯泛粹,在Aop中的前置,后置器仗,環(huán)繞等通知都有對應(yīng)攔截器實現(xiàn)
再來看下MethodInvocation的定義
MethodInvocation中proceed方法比較重要
/**
* Proceeds to the next interceptor in the chain.
*
* <p>The implementation and the semantics of this method depends
* on the actual joinpoint type (see the children interfaces).
*
* @return see the children interfaces' proceed definition.
*
* @throws Throwable if the joinpoint throws an exception. */
Object proceed() throws Throwable;
proceed()方法封裝了調(diào)用下一個攔截器的邏輯,如果攔截器執(zhí)行完畢童番,那么就執(zhí)行被代理方法
目前在spring框架里面MethodInvocation接口的實現(xiàn)類只有一個精钮,就是ReflectiveMethodInvocation
看下它的proceed方法實現(xiàn)
public Object proceed() throws Throwable {
// We start with an index of -1 and increment early.
if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
return invokeJoinpoint();
}
Object interceptorOrInterceptionAdvice =
this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
// Evaluate dynamic method matcher here: static part will already have
// been evaluated and found to match.
InterceptorAndDynamicMethodMatcher dm =
(InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
if (dm.methodMatcher.matches(this.method, this.targetClass, this.arguments)) {
return dm.interceptor.invoke(this);
}
else {
// Dynamic matching failed.
// Skip this interceptor and invoke the next in the chain.
return proceed();
}
}
else {
// It's an interceptor, so we just invoke it: The pointcut will have
// been evaluated statically before this object was constructed.
return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
}
}
這里會依次執(zhí)行攔截器,最后執(zhí)行被代理的方法
其中InterceptorAndDynamicMethodMatcher為動態(tài)攔截器剃斧,根據(jù)運行時參數(shù)來決定攔截器是否生效
有動態(tài)攔截器當(dāng)然也有靜態(tài)攔截器轨香,靜態(tài)攔截器一般通過包名,類名幼东,方法名 臂容,參數(shù)來確定靜態(tài)攔截器是否對代理方法生效
proceed方法中的interceptorsAndDynamicMethodMatchers攔截器鏈就是由AdvisedSupport的getInterceptorsAndDynamicInterceptionAdvice來獲取,接下來看下獲取攔截器鏈的具體實現(xiàn)
public List<Object> getInterceptorsAndDynamicInterceptionAdvice(Method method, Class<?> targetClass) {
MethodCacheKey cacheKey = new MethodCacheKey(method);
List<Object> cached = this.methodCache.get(cacheKey);
if (cached == null) {
cached = this.advisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice(
this, method, targetClass);
this.methodCache.put(cacheKey, cached);
}
return cached;
}
這個方法對需要獲取的攔截器鏈做了緩存根蟹,實際獲取邏輯委托給DefaultAdvisorChainFactory來實現(xiàn)
public interface AdvisorChainFactory {
/**
* Determine a list of {@link org.aopalliance.intercept.MethodInterceptor} objects
* for the given advisor chain configuration.
* @param config the AOP configuration in the form of an Advised object
* @param method the proxied method
* @param targetClass the target class (may be {@code null} to indicate a proxy without
* target object, in which case the method's declaring class is the next best option)
* @return List of MethodInterceptors (may also include InterceptorAndDynamicMethodMatchers)
*/
List<Object> getInterceptorsAndDynamicInterceptionAdvice(Advised config, Method method, Class<?> targetClass);
}
在DefaultAdvisorChainFactory的getInterceptorsAndDynamicInterceptionAdvice(Advised config, Method method, Class<?> targetClass)方法中脓杉,遍歷AdviseSupport里面配置的所有advisors,并且執(zhí)行PointCut中MethodMatcher的matches方法來決定對應(yīng)Advice是否生效娜亿,最后得到代理方法的攔截器鏈
具體代碼邏輯如下
AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();
for (Advisor advisor : config.getAdvisors()) {
if (advisor instanceof PointcutAdvisor) {
// Add it conditionally.
PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor;
if (config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(actualClass)) {
MethodInterceptor[] interceptors = registry.getInterceptors(advisor);
MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher();
if (MethodMatchers.matches(mm, method, actualClass, hasIntroductions)) {
if (mm.isRuntime()) {
// Creating a new object instance in the getInterceptors() method
// isn't a problem as we normally cache created chains.
for (MethodInterceptor interceptor : interceptors) {
interceptorList.add(new InterceptorAndDynamicMethodMatcher(interceptor, mm));
}
}
else {
interceptorList.addAll(Arrays.asList(interceptors));
}
}
}
}
else if (advisor instanceof IntroductionAdvisor) {
IntroductionAdvisor ia = (IntroductionAdvisor) advisor;
if (config.isPreFiltered() || ia.getClassFilter().matches(actualClass)) {
Interceptor[] interceptors = registry.getInterceptors(advisor);
interceptorList.addAll(Arrays.asList(interceptors));
}
}
else {
Interceptor[] interceptors = registry.getInterceptors(advisor);
interceptorList.addAll(Arrays.asList(interceptors));
}
}
注意到將Advisor轉(zhuǎn)換為Interceptor攔截器使用了registry.getInterceptors(advisor)丽已,轉(zhuǎn)換的邏輯委托給了AdvisorAdapterRegistry實現(xiàn),注意下轉(zhuǎn)換后得到的是數(shù)組买决,因為Advisor可配置多個Advice
AdvisorAdapterRegistry接口定義如下
public interface AdvisorAdapterRegistry {
Advisor wrap(Object advice) throws UnknownAdviceTypeException;
MethodInterceptor[] getInterceptors(Advisor advisor) throws UnknownAdviceTypeException;
void registerAdvisorAdapter(AdvisorAdapter adapter);
}
其中g(shù)etInterceptors方法實現(xiàn)如下
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()]);
}
在這個方法里面主要通過AdvisorAdapter 來把Advisor里面的Adivce(通知)轉(zhuǎn)換為對應(yīng)的攔截器MethodInterceptor
AdvisorAdapter接口定義如下
public interface AdvisorAdapter {
boolean supportsAdvice(Advice advice);
MethodInterceptor getInterceptor(Advisor advisor);
}
從接口推斷出沛婴,每種類型Advisor都會有一個AdvisorAdapter接口實現(xiàn)對應(yīng)
在DefaultAdvisorAdapterRegistry中默認(rèn)注冊了3個AdvisorAdapter
public DefaultAdvisorAdapterRegistry() {
registerAdvisorAdapter(new MethodBeforeAdviceAdapter());
registerAdvisorAdapter(new AfterReturningAdviceAdapter());
registerAdvisorAdapter(new ThrowsAdviceAdapter());
}
注意到并沒有環(huán)繞通知,因為環(huán)繞通知直接采用MethodInteceptor來實現(xiàn)
在getInterceptors方法里面可以看到
if (advice instanceof MethodInterceptor) {
interceptors.add((MethodInterceptor) advice);
}
這句代碼就是為了給環(huán)繞通知做處理
看下AdvisorAdapter和對應(yīng)攔截器的具體實現(xiàn)能讓我們理解更加深刻督赤,我們來看下MethodBeforeAdviceAdapter和MethodBeforeAdviceInterceptor
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);
}
}
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();
}
}
轉(zhuǎn)換攔截器的作用主要是形成鏈?zhǔn)秸{(diào)用嘁灯,在攔截器的invoke方法都會觸發(fā)調(diào)用下一個攔截器
總結(jié)
這個類的主要作用是將Advisor轉(zhuǎn)換為有效攔截器鏈,接下來我們只要關(guān)注怎么生成代理對象躲舌,以及在代理對象中怎么調(diào)用攔截器鏈