Spring中AOP相關(guān)的API及源碼解析,原來AOP是這樣子的

?
本系列文章:談?wù)凷pring中的對(duì)象跟Bean,你知道Spring怎么創(chuàng)建對(duì)象的嗎?
推薦閱讀:
本系列文章將會(huì)帶你一行行的將Spring的源碼吃透,推薦閱讀的文章是閱讀源碼的基礎(chǔ)!
因?yàn)楸疚臅?huì)涉及到動(dòng)態(tài)代理的相關(guān)內(nèi)容,如果對(duì)動(dòng)態(tài)代理不是很了解的話,參考文章:
動(dòng)態(tài)代理學(xué)習(xí)(一)自己動(dòng)手模擬JDK動(dòng)態(tài)代理
動(dòng)態(tài)代理學(xué)習(xí)(二)JDK動(dòng)態(tài)代理源碼分析
”
前言
之所以寫這么一篇文章主要是因?yàn)橄缕恼聦⒔Y(jié)束Spring啟動(dòng)整個(gè)流程的分析,從解析配置到創(chuàng)建對(duì)象再到屬性注入最后再將創(chuàng)建好的對(duì)象初始化成為一個(gè)真正意義上的Bean。因?yàn)橄缕恼聲?huì)涉及到AOP,所以提前單獨(dú)將AOP的相關(guān)API及源碼做一次解讀,這樣可以降低閱讀源碼的障礙,話不多說,我們進(jìn)入正文!
一個(gè)使用API創(chuàng)建代理的例子
在進(jìn)入API分析前,我們先通過兩個(gè)例子體會(huì)下如何使用API的方式來創(chuàng)建一個(gè)代理對(duì)象,對(duì)應(yīng)示例如下:
定義通知
public?class?DmzAfterReturnAdvice?implements?AfterReturningAdvice?{
?@Override
?public?void?afterReturning(@Nullable?Object?returnValue,?Method?method,?Object[]?args,?@Nullable?Object?target)?throws?Throwable?{
??System.out.println("after?invoke?method?["?+?method.getName()?+?"],aop?afterReturning?logic?invoked");
?}
}
public?class?DmzAroundAdvice?implements?MethodInterceptor?{
?@Override
?public?Object?invoke(MethodInvocation?invocation)?throws?Throwable?{
??System.out.println("aroundAdvice?invoked");
??return?invocation.proceed();
?}
}
public?class?DmzBeforeAdvice?implements?MethodBeforeAdvice?{
?@Override
?public?void?before(Method?method,?Object[]?args,?Object?target)?throws?Throwable?{
??System.out.println("before?invoke?method?["?+?method.getName()?+?"],aop?before?logic?invoked");
?}
}
public?class?DmzIntroductionAdvice?extends?DelegatingIntroductionInterceptor?implements?Runnable?{
?@Override
?public?void?run()?{
??System.out.println("running!!!!");
?}
}
切點(diǎn)
public?class?DmzPointcut?implements?Pointcut?{
?@Override
?@NonNull
?public?ClassFilter?getClassFilter()?{
??//?在類級(jí)別上不進(jìn)行攔截
??return?ClassFilter.TRUE;
?}
?@Override
?@NonNull
?public?MethodMatcher?getMethodMatcher()?{
??return?new?StaticMethodMatcherPointcut()?{
???@Override
???public?boolean?matches(@NonNull?Method?method,?Class>?targetClass)?{
????//?對(duì)于toString方法不進(jìn)行攔截
????return?!method.getName().equals("toString");
???}
??};
?}
}
目標(biāo)類
public?class?DmzService?{
?@Override
?public?String?toString()?{
??System.out.println("dmzService?toString?invoke");
??return?"dmzService";
?}
?public?void?testAop(){
??System.out.println("testAop?invoke");
?}
}
測(cè)試代碼
public?class?Main?{
?public?static?void?main(String[]?args)?{
??ProxyFactory?proxyFactory?=?new?ProxyFactory();
??//?一個(gè)Advisor代表的是一個(gè)已經(jīng)跟指定切點(diǎn)綁定了的通知
????????//?在這個(gè)例子中意味著環(huán)繞通知不會(huì)作用到toString方法上
??Advisor?advisor?=?new?DefaultPointcutAdvisor(new?DmzPointcut(),?new?DmzAroundAdvice());
??//?添加一個(gè)綁定了指定切點(diǎn)的環(huán)繞通知
??proxyFactory.addAdvisor(advisor);
??//?添加一個(gè)返回后的通知
??proxyFactory.addAdvice(new?DmzAfterReturnAdvice());
??//?添加一個(gè)方法執(zhí)行前的通知
??proxyFactory.addAdvice(new?DmzBeforeAdvice());
??//?為代理類引入一個(gè)新的需要實(shí)現(xiàn)的接口--Runnable
??proxyFactory.addAdvice(new?DmzIntroductionAdvice());
??//?設(shè)置目標(biāo)類
??proxyFactory.setTarget(new?DmzService());
??//?因?yàn)橐獪y(cè)試代理對(duì)象自己定義的方法,所以這里啟用cglib代理
??proxyFactory.setProxyTargetClass(true);
??//?創(chuàng)建代理對(duì)象
??Object?proxy?=?proxyFactory.getProxy();
??//?調(diào)用代理類的toString方法,通過控制臺(tái)查看代理邏輯的執(zhí)行情況
??proxy.toString();
??if?(proxy?instanceof?DmzService)?{
???((DmzService)?proxy).testAop();
??}
??//?判斷引入是否成功,并執(zhí)行引入的邏輯
??if?(proxy?instanceof?Runnable)?{
???((Runnable)?proxy).run();
??}
?}
}
這里我就不將測(cè)試結(jié)果放出來了,大家可以先自行思考這段程序?qū)⑤敵鍪裁础=酉聛砦覀兙蛠矸治錾厦孢@段程序中所涉及到的API,通過這些API的學(xué)習(xí)相信大家可以徹底理解上面這段代碼。
API介紹
Pointcut(切點(diǎn))
對(duì)應(yīng)接口定義如下:
public?interface?Pointcut?{
?
????//?ClassFilter,在類級(jí)別進(jìn)行過濾
?ClassFilter?getClassFilter();
????
?//?MethodMatcher,在方法級(jí)別進(jìn)行過濾
?MethodMatcher?getMethodMatcher();
?
????//?一個(gè)單例對(duì)象,默認(rèn)匹配所有
?Pointcut?TRUE?=?TruePointcut.INSTANCE;
}
切點(diǎn)的主要作用是定義通知所要應(yīng)用到的類跟方法,上面的接口定義也很明顯的體現(xiàn)了這一點(diǎn),我們可以將其拆分成為兩個(gè)部分
ClassFilter,接口定義如下:
public?interface?ClassFilter?{
?boolean?matches(Class>?clazz);
?ClassFilter?TRUE?=?TrueClassFilter.INSTANCE;
}
ClassFilter的主要作用是在類級(jí)別上對(duì)通知的應(yīng)用進(jìn)行一次過濾,如果它的match方法對(duì)任意的類都返回true的話,說明在類級(jí)別上我們不需要過濾,這種情況下,通知的應(yīng)用,就完全依賴MethodMatcher的匹配結(jié)果。
MethodMatcher,接口定義如下:
public?interface?MethodMatcher?{
?boolean?matches(Method?method,?@Nullable?Class>?targetClass);
?boolean?isRuntime();
?boolean?matches(Method?method,?@Nullable?Class>?targetClass,?Object...?args);
?MethodMatcher?TRUE?=?TrueMethodMatcher.INSTANCE;
}
MethodMatcher中一共有三個(gè)核心方法
matches(Method method, @Nullable Class> targetClass),這個(gè)方法用來判斷當(dāng)前定義的切點(diǎn)跟目標(biāo)類中的指定方法是否匹配,它可以在創(chuàng)建代理的時(shí)候就被調(diào)用,從而決定是否需要進(jìn)行代理,這樣就可以避免每次方法執(zhí)行的時(shí)候再去做判斷isRuntime(),如果這個(gè)方法返回true的話,意味著每次執(zhí)行方法時(shí)還需要做一次匹配matches(Method method, @Nullable Class> targetClass, Object... args),當(dāng)之前的isRuntime方法返回true時(shí),會(huì)調(diào)用這個(gè)方法再次進(jìn)行一次判斷,返回false的話,意味這個(gè)不對(duì)這個(gè)方法應(yīng)用通知
Advice(通知)
環(huán)繞通知(Interception Around Advice)
接口定義如下:
public?interface?MethodInterceptor?extends?Interceptor?{
????Object?invoke(MethodInvocation?invocation)?throws?Throwable;
}
在上面接口定義的invoke方法中,MethodInvocation就是當(dāng)前執(zhí)行的方法,當(dāng)我們調(diào)用invocation.proceed就是在執(zhí)行當(dāng)前的這個(gè)方法,基于此,我們可以在方法的執(zhí)行前后去插入我們自定義的邏輯,比如下面這樣
//?執(zhí)行前的邏輯
doSomeThingBefore();
Object?var?=?invocation.proceed;
doSomeThingAfter();
//?執(zhí)行后的邏輯
retrun?var;
前置通知(Before Advice)
public?interface?MethodBeforeAdvice?extends?BeforeAdvice?{
????void?before(Method?m,?Object[]?args,?Object?target)?throws?Throwable;
}
跟環(huán)繞通知不同的是,這個(gè)接口中定義的方法的返回值是void,所以前置通知是無法修改方法的返回值的。
如果在前置通知中發(fā)生了異常,那么會(huì)直接終止目標(biāo)方法的執(zhí)行以及打斷整個(gè)攔截器鏈的執(zhí)行
后置通知(After Returning Advice)
public?interface?AfterReturningAdvice?extends?Advice?{
????void?afterReturning(Object?returnValue,?Method?m,?Object[]?args,?Object?target)
????????????throws?Throwable;
}
后置通知相比較于前置通知,主要有以下幾點(diǎn)不同
后置通知可以訪問目標(biāo)方法的返回值,但是不能修改 后置通知是在方法執(zhí)行完成后執(zhí)行
異常通知(Throws Advice)
public?interface?ThrowsAdvice?extends?AfterAdvice?{
}
異常通知中沒有定義任何方法,它更像一個(gè)標(biāo)記接口。我們?cè)诙x異常通知時(shí)需要實(shí)現(xiàn)這個(gè)接口,同時(shí)方法的簽名也有要求
方法名稱必須是 afterThrowing方法的參數(shù)個(gè)數(shù)必須是1個(gè)或者4個(gè),如下:
public?class?OneParamThrowsAdvice?implements?ThrowsAdvice?{
????//?如果只有一個(gè)參數(shù),那么這個(gè)參數(shù)必須是要進(jìn)行處理的異常
????public?void?afterThrowing(RemoteException?ex)?throws?Throwable?{
????????//?Do?something?with?remote?exception
????}
}
public?class?FourParamThrowsAdvice?implements?ThrowsAdvice?{
?
????//?如果定義了四個(gè)參數(shù),那么這四個(gè)參數(shù)分別是
????// 1.m:目標(biāo)方法
????// 2.args:執(zhí)行目標(biāo)方法所需要的參數(shù)
????// 3.target:目標(biāo)對(duì)象
????// 4.ex:具體要處理的異常
????//?并且參數(shù)類型必須按照這個(gè)順序定義
????public?void?afterThrowing(Method?m,?Object[]?args,?Object?target,?ServletException?ex)?{
????????//?Do?something?with?all?arguments
????}
}
我們可以在一個(gè)異常通知中定義多個(gè)方法,在后續(xù)的源碼分析中我們會(huì)發(fā)現(xiàn),這些方法最終會(huì)被注冊(cè)成對(duì)應(yīng)的異常的handler,像下面這樣
public?static?class?CombinedThrowsAdvice?implements?ThrowsAdvice?{
????public?void?afterThrowing(RemoteException?ex)?throws?Throwable?{
????????//?Do?something?with?remote?exception
????}
????public?void?afterThrowing(Method?m,?Object[]?args,?Object?target,?ServletException?ex)?{
????????//?Do?something?with?all?arguments
????}
}
引入通知(Introduction Advice)
引入通知的主要作用是可以讓生成的代理類實(shí)現(xiàn)額外的接口。例如在上面的例子中,我們?yōu)?code style="overflow-wrap: break-word;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(255, 93, 108);">DmzService創(chuàng)建一個(gè)代理對(duì)象,同時(shí)為其定義了一個(gè)引入通知
public?class?DmzIntroductionAdvice?extends?DelegatingIntroductionInterceptor?implements?Runnable?{
?@Override
?public?void?run()?{
??System.out.println("running!!!!");
?}
}
在這個(gè)引入通知中,我們?yōu)槠湟肓艘粋€(gè)新的需要實(shí)現(xiàn)的接口Runnable,同時(shí)通知本身作為這個(gè)接口的實(shí)現(xiàn)類。
通過這個(gè)引入通知,我們可以將生成的代理類強(qiáng)轉(zhuǎn)成Runnable類型然后執(zhí)行其run方法,同時(shí),run方法也會(huì)被前面定義的前置通知,后置通知等攔截。
為了更好的了解引入通知,我們來需要了解下DelegatingIntroductionInterceptor這個(gè)類。見名知意,這個(gè)類就是一個(gè)委托引入攔截器,因?yàn)槲覀円獮榇眍愐胄碌慕涌冢驗(yàn)橹覀円峁┚唧w的實(shí)現(xiàn)的邏輯,而具體的實(shí)現(xiàn)的邏輯就可以被委托給這個(gè)DelegatingIntroductionInterceptor。
我們可以看看它的源碼
public?class?DelegatingIntroductionInterceptor?extends?IntroductionInfoSupport
??implements?IntroductionInterceptor?{
?
????//?實(shí)際實(shí)現(xiàn)了引入邏輯的類
?@Nullable
?private?Object?delegate;
?
????//?對(duì)外提供了一個(gè)帶參的構(gòu)造函數(shù),通過這個(gè)構(gòu)造函數(shù)我們可以傳入一個(gè)
????//?具體的實(shí)現(xiàn)類
?public?DelegatingIntroductionInterceptor(Object?delegate)?{
??init(delegate);
?}
????//?對(duì)子類暴露了一個(gè)空參的構(gòu)造函數(shù),默認(rèn)將自身作為實(shí)現(xiàn)了引入邏輯的委托類
????//?我們上面的例子中就是使用的這種方法
?protected?DelegatingIntroductionInterceptor()?{
??init(this);
?}
?
????//?對(duì)這個(gè)類進(jìn)行初始化,要通過實(shí)際的實(shí)現(xiàn)類來找到具體要實(shí)現(xiàn)的接口
?private?void?init(Object?delegate)?{
??Assert.notNull(delegate,?"Delegate?must?not?be?null");
??this.delegate?=?delegate;
????????
????????//?找到delegate所有實(shí)現(xiàn)的接口
??implementInterfacesOnObject(delegate);
??
????????//?因?yàn)槲覀兛赡軙?huì)將DelegatingIntroductionInterceptor本身作為委托者
????????//?Spring的設(shè)計(jì)就是不對(duì)外暴露這兩個(gè)接口
????????//?如果將其暴露,意味著我們可以將代理類強(qiáng)轉(zhuǎn)成這種類型
??suppressInterface(IntroductionInterceptor.class);
??suppressInterface(DynamicIntroductionAdvice.class);
?}
?//?引入通知本身也是基于攔截器實(shí)現(xiàn)的,當(dāng)執(zhí)行一個(gè)方法時(shí)需要判斷這個(gè)方法
????//?是不是被引入的接口中定義的方法,如果是的話,那么不能調(diào)用目標(biāo)類的方法
????//?而要調(diào)用委托類的方法
?public?Object?invoke(MethodInvocation?mi)?throws?Throwable?{
??if?(isMethodOnIntroducedInterface(mi))?{
???Object?retVal?=?AopUtils.invokeJoinpointUsingReflection(this.delegate,?mi.getMethod(),?mi.getArguments());
???//?這里是處理一種特殊情況,方法的返回值是this的時(shí)候
????????????//?這里應(yīng)該返回代理類
???if?(retVal?==?this.delegate?&&?mi?instanceof?ProxyMethodInvocation)?{
????Object?proxy?=?((ProxyMethodInvocation)?mi).getProxy();
????if?(mi.getMethod().getReturnType().isInstance(proxy))?{
?????retVal?=?proxy;
????}
???}
????????????//?其余情況下直接將委托類的執(zhí)行結(jié)果返回
???return?retVal;
??}
????????//?執(zhí)行到這里說明不是引入的方法,這是Spring提供了一個(gè)擴(kuò)展邏輯
????????//?正常來說這個(gè)類只會(huì)處理引入的邏輯,通過這個(gè)方法可以對(duì)目標(biāo)類中的方法做攔截
????????//?不常用
??return?doProceed(mi);
?}
?protected?Object?doProceed(MethodInvocation?mi)?throws?Throwable?{
??return?mi.proceed();
?}
}
通過查看這個(gè)類的源碼我們可以發(fā)現(xiàn),所謂的引入其實(shí)就是在方法執(zhí)行的時(shí)候加了一層攔截,當(dāng)判斷這個(gè)方法是被引入的接口提供的方法的時(shí)候,那么就執(zhí)行委托類中的邏輯而不是目標(biāo)類中的方法
關(guān)于通知的總結(jié)
通過上文的分析我們可以發(fā)現(xiàn),通知總共可以分為這么幾類
普通的通知(前置,后置,異常等,沒有實(shí)現(xiàn) MethodInterceptor接口)環(huán)繞通知(實(shí)現(xiàn)了 MethodInterceptor接口)引入通知(需要提供額外的引入的信息,實(shí)現(xiàn)了 MethodInterceptor接口)
上面的分類并不標(biāo)準(zhǔn),只是為了方便大家記憶跟理解,雖然我們普通的通知沒有直接實(shí)現(xiàn)MethodInterceptor接口,但其實(shí)它的底層也是依賴于攔截器來完成的,大家可以看看下面這個(gè)類
class?MethodBeforeAdviceAdapter?implements?AdvisorAdapter,?Serializable?{
?@Override
?public?boolean?supportsAdvice(Advice?advice)?{
??return?(advice?instanceof?MethodBeforeAdvice);
?}
?
????//?根據(jù)傳入的一個(gè)前置通知,創(chuàng)建一個(gè)對(duì)應(yīng)的攔截器
?@Override
?public?MethodInterceptor?getInterceptor(Advisor?advisor)?{
??MethodBeforeAdvice?advice?=?(MethodBeforeAdvice)?advisor.getAdvice();
??return?new?MethodBeforeAdviceInterceptor(advice);
?}
}
public?class?MethodBeforeAdviceInterceptor?implements?MethodInterceptor,?BeforeAdvice,?Serializable?{
?private?final?MethodBeforeAdvice?advice;
?public?MethodBeforeAdviceInterceptor(MethodBeforeAdvice?advice)?{
??Assert.notNull(advice,?"Advice?must?not?be?null");
??this.advice?=?advice;
?}
?//?實(shí)際上還是利用攔截器,在方法執(zhí)行前調(diào)用了通知的before方法完成了前置通知
?@Override
?public?Object?invoke(MethodInvocation?mi)?throws?Throwable?{
??this.advice.before(mi.getMethod(),?mi.getArguments(),?mi.getThis());
??return?mi.proceed();
?}
}
Advisor (綁定通知跟切點(diǎn))
一個(gè)Advisor實(shí)際上就是一個(gè)綁定在指定切點(diǎn)上的通知。在前面的例子我們可以發(fā)現(xiàn),有兩種添加通知的方式
//?一個(gè)Advisor代表的是一個(gè)已經(jīng)跟指定切點(diǎn)綁定了的通知
//?在這個(gè)例子中意味著環(huán)繞通知不會(huì)作用到toString方法上
Advisor?advisor?=?new?DefaultPointcutAdvisor(new?DmzPointcut(),?new?DmzAroundAdvice());
//?添加一個(gè)綁定了指定切點(diǎn)的環(huán)繞通知
proxyFactory.addAdvisor(advisor);
//?添加一個(gè)返回后的通知
proxyFactory.addAdvice(new?DmzAfterReturnAdvice());
一種是直接添加了一個(gè)Advisor,還有一種是添加一個(gè)Advice,后者也會(huì)被轉(zhuǎn)換成一個(gè)Advisor然后再進(jìn)行添加,沒有指定切點(diǎn)的通知是沒有任何意義的
public?void?addAdvice(Advice?advice)?throws?AopConfigException?{
????int?pos?=?this.advisors.size();
????//?默認(rèn)添加到集合的最后一個(gè)位置
????addAdvice(pos,?advice);
}
//?這個(gè)方法添加通知
public?void?addAdvice(int?pos,?Advice?advice)?throws?AopConfigException?{
????Assert.notNull(advice,?"Advice?must?not?be?null");
????
????//?如果是一個(gè)引入通知,那么構(gòu)建一個(gè)DefaultIntroductionAdvisor
????//?DefaultIntroductionAdvisor會(huì)匹配所有類
????if?(advice?instanceof?IntroductionInfo)?{
????????addAdvisor(pos,?new?DefaultIntroductionAdvisor(advice,?(IntroductionInfo)?advice));
????}
????//?不能直接添加一個(gè)不是IntroductionInfo的DynamicIntroductionAdvice(動(dòng)態(tài)引入通知)
????else?if?(advice?instanceof?DynamicIntroductionAdvice)?{
????????throw?new?AopConfigException("DynamicIntroductionAdvice?may?only?be?added?as?part?of?IntroductionAdvisor");
????}
????else?{
????????//?如果是普通的通知,那么會(huì)創(chuàng)建一個(gè)DefaultPointcutAdvisor
????????//?DefaultPointcutAdvisor所定義的切點(diǎn)會(huì)匹配所有類以及所有方法
????????addAdvisor(pos,?new?DefaultPointcutAdvisor(advice));
????}
}
ProxyCreatorSupport
這個(gè)類的主要作用是為創(chuàng)建一個(gè)AOP代理對(duì)象提供一些功能支持,通過它的getAopProxyFactory能獲取一個(gè)創(chuàng)建代理對(duì)象的工廠。
//?這里我只保留了這個(gè)類中的關(guān)鍵代碼
public?class?ProxyCreatorSupport?extends?AdvisedSupport?{?
????private?AopProxyFactory?aopProxyFactory;
????//?空參構(gòu)造,默認(rèn)會(huì)創(chuàng)建一個(gè)DefaultAopProxyFactory
????//?通過這個(gè)ProxyFactory可以創(chuàng)建一個(gè)cglib代理或者jdk代理
????public?ProxyCreatorSupport()?{
????????this.aopProxyFactory?=?new?DefaultAopProxyFactory();
????}
????//?通過這個(gè)方法可以創(chuàng)建一個(gè)具體的代理對(duì)象
????protected?final?synchronized?AopProxy?createAopProxy()?{
????????if?(!this.active)?{
????????????activate();
????????}
????????//?實(shí)際就是使用DefaultAopProxyFactory來創(chuàng)建一個(gè)代理對(duì)象
????????//?可以看到在調(diào)用createAopProxy方法時(shí),傳入的參數(shù)是this
????????//?這是因?yàn)镻roxyCreatorSupport本身就保存了創(chuàng)建整個(gè)代理對(duì)象所需要的配置信息
????????return?getAopProxyFactory().createAopProxy(this);
????}
}

另外通過上面的UML類圖還能看到,ProxyCreatorSupport繼承了AdvisedSupport,AdvisedSupport繼承了ProxyConfig。
ProxyConfig
其中ProxyConfig是所有的AOP代理工廠的父類,它包含了創(chuàng)建一個(gè)AOP代理所需要的基礎(chǔ)的通用的一些配置信息
//?這里省略了一些getter跟setter方法
public?class?ProxyConfig?implements?Serializable?{
?
????//?是否開啟cglib代理,默認(rèn)不開啟使用jdk動(dòng)態(tài)代理
?private?boolean?proxyTargetClass?=?false;
????//?是否啟用優(yōu)化,默認(rèn)為false,按照官網(wǎng)對(duì)這個(gè)參數(shù)的解釋
????//?這個(gè)優(yōu)化是針對(duì)cglib,如果設(shè)計(jì)為true的話,會(huì)做一些侵入性的優(yōu)化
????//?是否開啟在jdk代理的情況下沒有影響
????//?官網(wǎng)中特地說明了,除非對(duì)cglib的優(yōu)化非常了解,否則不要開啟這個(gè)參數(shù)
?private?boolean?optimize?=?false;
?
????//?生成的代理類是否需要實(shí)現(xiàn)Advised接口,這個(gè)接口可以向外提供操作通知的方法
????//?如果為false會(huì)實(shí)現(xiàn)
????//?為true的話,不會(huì)實(shí)現(xiàn)
?boolean?opaque?=?false;
?
????//?是否將當(dāng)前的配置類暴露到一個(gè)線程上下文中,如果設(shè)置為true的話
????//?可以通過AopContext.currentProxy()來獲取到當(dāng)前的代理對(duì)象
?boolean?exposeProxy?=?false;
????
????//?標(biāo)志著是否凍結(jié)整個(gè)配置,如果凍結(jié)了,那么配置信息將不允許修改
?private?boolean?frozen?=?false;
}
AdvisedSupport
當(dāng)我們?yōu)槟硞€(gè)對(duì)象創(chuàng)建代理時(shí),除了需要上面的ProxyConfig提供的一些基礎(chǔ)配置外,起碼還需要知道
需要執(zhí)行的通知是哪些? 目標(biāo)對(duì)象是誰? 創(chuàng)建出來的代理需要實(shí)現(xiàn)哪些接口?
而這些配置信息是由AdvisedSupport提供的,AdvisedSupport本身實(shí)現(xiàn)了Advised接口,Advised接口定義了管理通知的方法。
在了解了上面的API后我們來看看Spring提供了幾種創(chuàng)建AOP代理的方式
ProxyFactoryBean ProxyFactory Auto-proxy
ProxyFactoryBean的方式創(chuàng)建AOP代理
使用示例
<beans?xmlns="http://www.springframework.org/schema/beans"
????xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
????xsi:schemaLocation="http://www.springframework.org/schema/beans?http://www.springframework.org/schema/beans/spring-beans.xsd">
?<bean?class="com.dmz.spring.initalize.service.DmzService"?name="dmzService"/>
?<bean?id="aroundAdvice"?class="com.dmz.spring.initalize.aop.advice.DmzAroundAdvice"/>
?<bean?id="dmzProxy"
????class="org.springframework.aop.framework.ProxyFactoryBean">
????????
??<property?name="proxyInterfaces"?value="java.lang.Runnable"/>
??<property?name="proxyTargetClass"?value="true"/>
???<property?name="target"?ref="dmzService"/>
??<property?name="interceptorNames">
???<list>
????<value>aroundAdvicevalue>
???list>
??property>
?bean>
beans>
//?目標(biāo)類
public?class?DmzService?{
?@Override
?public?String?toString()?{
??System.out.println("dmzService?toString?invoke");
??return?"dmzService";
?}
?public?void?testAop(){
??System.out.println("testAop?invoke");
?}
}
//?通知
public?class?DmzAroundAdvice?implements?MethodInterceptor?{
?@Override
?public?Object?invoke(MethodInvocation?invocation)?throws?Throwable?{
??System.out.println("aroundAdvice?invoked");
??return?invocation.proceed();
?}
}
public?class?SourceMain?{
?public?static?void?main(String[]?args)?{
??ClassPathXmlApplicationContext?cc?=
????new?ClassPathXmlApplicationContext("application-init.xml");
??DmzService?dmzProxy?=?((DmzService)?cc.getBean("dmzProxy"));
??dmzProxy.testAop();
?}
}
ProxyFactoryBean介紹
跟普通的FactoryBean一樣,這個(gè)類的主要作用就是通過getObject方法能夠獲取一個(gè)Bean,不同的是這個(gè)類獲取到的是代理后的Bean。
我們查看這個(gè)類的繼承關(guān)系可以發(fā)現(xiàn)

這個(gè)類除了實(shí)現(xiàn)了FactoryBean接口以及一些Aware接口外,額外還繼承了ProxyCreatorSupport類。它是一個(gè)factoryBean,所以我們重點(diǎn)就關(guān)注它的getObject方法即可。
public?Object?getObject()?throws?BeansException?{
????//?初始化通知鏈
????//?這里主要就是將在XML中配置的通知添加到
????//?AdvisedSupport管理的配置中去
????initializeAdvisorChain();
????if?(isSingleton())?{
????????//?如果是單例的,那么獲取一個(gè)單例的代理對(duì)象
????????return?getSingletonInstance();
????}
????else?{
????????if?(this.targetName?==?null)?{
????????????logger.warn("Using?non-singleton?proxies?with?singleton?targets?is?often?undesirable.?"?+
????????????????????????"Enable?prototype?proxies?by?setting?the?'targetName'?property.");
????????}
????????//?如果是原型的,獲取一個(gè)原型的代理對(duì)象
????????return?newPrototypeInstance();
????}
}
關(guān)于這段代碼就不做過多分析了,它其實(shí)就兩步(不管是哪種方式創(chuàng)建代理,都分為這兩步)
完善創(chuàng)建代理需要的配置信息 創(chuàng)建代理
其中配置信息分為兩部分,其一是AppConfig管理的通用的配置信息,其二是AdvisedSupport管理的通知信息。通用的配置信息我們可以直接在XML中配置,例如在上面的例子中我們就配置了proxyTargetClass屬性,而通知信息即使我們?cè)赬ML中配置了也還需要做一層轉(zhuǎn)換,在前面我們也提到過了,所有的Advice都會(huì)被轉(zhuǎn)換成Advisor添加到配置信息中。
ProxyFactory的方式創(chuàng)建AOP代理
使用示例(略,見開頭)
ProxyFactory介紹

從上面我們可以看出,ProxyFactory也繼承自ProxyCreatorSupport,從之前的例子我們也能感受到,使用它的API來創(chuàng)建一個(gè)代理對(duì)象也是要先去設(shè)置相關(guān)的配置信息,最后再調(diào)用創(chuàng)建代理的方法
我們之后要分析的自動(dòng)代理內(nèi)部就是通過創(chuàng)建了一個(gè)ProxyFactory來獲取代理對(duì)象的。
我們可以對(duì)比下ProxyFactoryBean跟ProxyFactory在創(chuàng)建代理對(duì)象時(shí)的代碼
ProxyFactory
public?Object?getProxy()?{
????//?調(diào)用了ProxyCreatorSupport的createAopProxy()方法創(chuàng)建一個(gè)AopProxy對(duì)象
????//?然后調(diào)用AopProxy對(duì)象的getProxy方法
????return?createAopProxy().getProxy();
}
ProxyFactoryBean
private?synchronized?Object?getSingletonInstance()?{
????if?(this.singletonInstance?==?null)?{
????????this.targetSource?=?freshTargetSource();
????????if?(this.autodetectInterfaces?&&?getProxiedInterfaces().length?==?0?&&?!isProxyTargetClass())?{
????????????Class>?targetClass?=?getTargetClass();
????????????if?(targetClass?==?null)?{
????????????????throw?new?FactoryBeanNotInitializedException("Cannot?determine?target?class?for?proxy");
????????????}
????????????setInterfaces(ClassUtils.getAllInterfacesForClass(targetClass,?this.proxyClassLoader));
????????}
????????super.setFrozen(this.freezeProxy);
????????//?重點(diǎn)就看這里
????????//?這里調(diào)用了ProxyCreatorSupport的createAopProxy()方法創(chuàng)建一個(gè)AopProxy對(duì)象
????????//?而getProxy方法就是調(diào)用創(chuàng)建的AopProxy的getProxy方法
????????this.singletonInstance?=?getProxy(createAopProxy());
????}
????return?this.singletonInstance;
}
protected?Object?getProxy(AopProxy?aopProxy)?{
????return?aopProxy.getProxy(this.proxyClassLoader);
}
綜上,我們可以得出結(jié)論,不管是通過哪種方式創(chuàng)建AOP代理,核心代碼就一句
createAopProxy().getProxy()
這句代碼也是我們接下來源碼分析的重點(diǎn)
Auto-proxy(實(shí)現(xiàn)自動(dòng)AOP代理)
自動(dòng)代理機(jī)制的實(shí)現(xiàn)其實(shí)很簡(jiǎn)單,就是通過Bean的后置處理器,在創(chuàng)建Bean的最后一步對(duì)Bean進(jìn)行代理,并將代理對(duì)象放入到容器中。
實(shí)現(xiàn)自動(dòng)代理的核心類就是AbstractAutoProxyCreator。我們來看看它的繼承關(guān)系

為了更好的體會(huì)自動(dòng)代理的作用,我們對(duì)它的三個(gè)具體的實(shí)現(xiàn)類來進(jìn)行分析,分別是
BeanNameAutoProxyCreatorDefaultAdvisorAutoProxyCreatorAnnotationAwareAspectJAutoProxyCreator
BeanNameAutoProxyCreator
使用示例
<beans?xmlns="http://www.springframework.org/schema/beans"
????xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
????xsi:schemaLocation="http://www.springframework.org/schema/beans?http://www.springframework.org/schema/beans/spring-beans.xsd">
?<bean?class="com.dmz.spring.initalize.service.DmzService"?name="dmzService"/>
?<bean?id="aroundAdvice"?class="com.dmz.spring.initalize.aop.advice.DmzAroundAdvice"/>
?<bean?id="beforeAdvice"?class="com.dmz.spring.initalize.aop.advice.DmzBeforeAdvice"/>
????
?<bean?class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator"?name="autoProxyCreator">
????????
??<property?name="proxyTargetClass"?value="true"/>
?????????
??<property?name="beanNames"?value="dmz*"/>
????????
??<property?name="interceptorNames">
???<list>
????<value>beforeAdvicevalue>
????<value>aroundAdvicevalue>
???list>
??property>
?bean>
beans>
public?class?SourceMain?{
?public?static?void?main(String[]?args)?{
??ClassPathXmlApplicationContext?cc?=
????new?ClassPathXmlApplicationContext("application-init.xml");
??DmzService?dmzProxy?=?((DmzService)?cc.getBean("dmzService"));
??dmzProxy.testAop();
?}
}
//?程序打印:
//?before?invoke?method?[testAop],aop?before?logic?invoked
//?aroundAdvice?invoked
//?testAop?invoke
DefaultAdvisorAutoProxyCreator
使用示例
在上面例子的基礎(chǔ)上我們要修改配置文件,如下:
<beans?xmlns="http://www.springframework.org/schema/beans"
????xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
????xsi:schemaLocation="http://www.springframework.org/schema/beans?http://www.springframework.org/schema/beans/spring-beans.xsd">
?<bean?class="com.dmz.spring.initalize.service.DmzService"?name="dmzService"/>
?<bean?id="aroundAdvice"?class="com.dmz.spring.initalize.aop.advice.DmzAroundAdvice"/>
?<bean?id="beforeAdvice"?class="com.dmz.spring.initalize.aop.advice.DmzBeforeAdvice"/>
?
?<bean?class="org.springframework.aop.support.DefaultPointcutAdvisor"?id="dmzBeforeAdvisor">
??<property?name="advice"?ref="beforeAdvice"/>
?bean>
?<bean?class="org.springframework.aop.support.DefaultPointcutAdvisor"?id="dmzAroundAdvisor">
??<property?name="advice"?ref="aroundAdvice"/>
?bean>
?<bean?class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"
????id="advisorAutoProxyCreator">
????????
??<property?name="usePrefix"?value="true"/>
??<property?name="advisorBeanNamePrefix"?value="dmz"/>
??
????????<property?name="proxyTargetClass"?value="true"/>
?bean>
beans>
測(cè)試代碼就不放了,大家可以自行測(cè)試,肯定是沒問題的
AnnotationAwareAspectJAutoProxyCreator
我們正常在使用AOP的時(shí)候都會(huì)在配置類上添加一個(gè)@EnableAspectJAutoProxy注解,這個(gè)注解干了什么事呢?
實(shí)際就是向容器中注冊(cè)了一個(gè)AnnotationAwareAspectJAutoProxyCreator。
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
//?這里導(dǎo)入了一個(gè)類
@Import(AspectJAutoProxyRegistrar.class)
public?@interface?EnableAspectJAutoProxy?{
?
?boolean?proxyTargetClass()?default?false;
?boolean?exposeProxy()?default?false;
}
通過@EnableAspectJAutoProxy導(dǎo)入了一個(gè)AspectJAutoProxyRegistrar,這個(gè)類會(huì)向容器中注冊(cè)一個(gè)AnnotationAwareAspectJAutoProxyCreator,對(duì)應(yīng)源碼如下:
class?AspectJAutoProxyRegistrar?implements?ImportBeanDefinitionRegistrar?{
?@Override
?public?void?registerBeanDefinitions(
???AnnotationMetadata?importingClassMetadata,?BeanDefinitionRegistry?registry)?{
??
????????//?在這里完成的注冊(cè)
??//?最終會(huì)調(diào)用到AopUtils的registerAspectJAnnotationAutoProxyCreatorIfNecessary方法
????????//?完成AnnotationAwareAspectJAutoProxyCreator這個(gè)bd的注冊(cè)
??AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);
??
????????//?解析注解的屬性
????????// proxyTargetClass:為true的話開啟cglib代理,默認(rèn)為jdk代理
????????// exposeProxy:是否將代理對(duì)象暴露到線程上下文中
??AnnotationAttributes?enableAspectJAutoProxy?=
????AnnotationConfigUtils.attributesFor(importingClassMetadata,?EnableAspectJAutoProxy.class);
??if?(enableAspectJAutoProxy?!=?null)?{
???if?(enableAspectJAutoProxy.getBoolean("proxyTargetClass"))?{
????AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
???}
??????????
???if?(enableAspectJAutoProxy.getBoolean("exposeProxy"))?{
????AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
???}
??}
?}
}
前面已經(jīng)說過了,自動(dòng)代理機(jī)制實(shí)際上就是Spring在內(nèi)部new了一個(gè)ProxyFactory,通過它創(chuàng)建了一個(gè)代理對(duì)象。對(duì)應(yīng)的代碼就在AbstractAutoProxyCreator中的createProxy方法內(nèi),源碼如下:
protected?Object?createProxy(Class>?beanClass,?@Nullable?String?beanName,
?????????????????????????????@Nullable?Object[]?specificInterceptors,?TargetSource?targetSource)?{
????if?(this.beanFactory?instanceof?ConfigurableListableBeanFactory)?{
????????AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory)?this.beanFactory,?beanName,?beanClass);
????}
?//?看到了吧,這里創(chuàng)建了一個(gè)proxyFactory
????ProxyFactory?proxyFactory?=?new?ProxyFactory();
????proxyFactory.copyFrom(this);
????if?(!proxyFactory.isProxyTargetClass())?{
????????if?(shouldProxyTargetClass(beanClass,?beanName))?{
????????????proxyFactory.setProxyTargetClass(true);
????????}
????????else?{
????????????evaluateProxyInterfaces(beanClass,?proxyFactory);
????????}
????}
????Advisor[]?advisors?=?buildAdvisors(beanName,?specificInterceptors);
????proxyFactory.addAdvisors(advisors);
????proxyFactory.setTargetSource(targetSource);
????customizeProxyFactory(proxyFactory);
????proxyFactory.setFrozen(this.freezeProxy);
????if?(advisorsPreFiltered())?{
????????proxyFactory.setPreFiltered(true);
????}
?//?通過proxyFactory來創(chuàng)建一個(gè)代理對(duì)象
????return?proxyFactory.getProxy(getProxyClassLoader());
}
關(guān)于這個(gè)類的執(zhí)行流程在下篇文章中我再詳細(xì)介紹,接下來我們要分析的就是具體創(chuàng)建AOP代理的源碼了。對(duì)應(yīng)的核心源碼就是我們之前所提到的
createAopProxy().getProxy();
這行代碼分為兩步,我們逐步分析
調(diào)用 AopProxyFactory的createAopProxy()方法獲取一個(gè)AopProxy對(duì)象調(diào)用 AopProxy對(duì)象的getProxy()方法
核心源碼分析
createAopProxy方法分析
AopProxyFactory在Spring中只有一個(gè)默認(rèn)的實(shí)現(xiàn)類,就是DefaultAopProxyFactory,它的對(duì)應(yīng)的createAopProxy的是實(shí)現(xiàn)代碼如下:
public?class?DefaultAopProxyFactory?implements?AopProxyFactory,?Serializable?{
?
????//?就是通過AOP相關(guān)的配置信息來決定到底是使用cglib代理還是jdk代理
????@Override
????public?AopProxy?createAopProxy(AdvisedSupport?config)?throws?AopConfigException?{
????????//?如果開啟了優(yōu)化,或者ProxyTargetClass設(shè)置為true
????????//?或者沒有提供代理類需要實(shí)現(xiàn)的接口,那么使用cglib代理
????????//?在前面分析參數(shù)的時(shí)候已經(jīng)說過了
????????//?默認(rèn)情況下Optimize都為false,也不建議設(shè)置為true,因?yàn)闀?huì)進(jìn)行一些侵入性的優(yōu)化
????????//?除非你對(duì)cglib的優(yōu)化非常了解,否則不建議開啟
????????if?(config.isOptimize()?||?config.isProxyTargetClass()?||?hasNoUserSuppliedProxyInterfaces(config))?{
????????????Class>?targetClass?=?config.getTargetClass();
????????????if?(targetClass?==?null)?{
????????????????throw?new?AopConfigException("TargetSource?cannot?determine?target?class:?"?+
?????????????????????????????????????????????"Either?an?interface?or?a?target?is?required?for?proxy?creation.");
????????????}
????????????//?需要注意的是,如果需要代理的類本身就是一個(gè)接口
????????????//?或者需要被代理的類本身就是一個(gè)通過jdk動(dòng)態(tài)代理生成的類
????????????//?那么不管如何設(shè)置都會(huì)使用jdk動(dòng)態(tài)代理
????????????if?(targetClass.isInterface()?||?Proxy.isProxyClass(targetClass))?{
????????????????return?new?JdkDynamicAopProxy(config);
????????????}
????????????return?new?ObjenesisCglibAopProxy(config);
????????}
????????//?否則都是jdk代理
????????else?{
????????????return?new?JdkDynamicAopProxy(config);
????????}
????}
?//?判斷是否提供代理類需要實(shí)現(xiàn)的接口
????private?boolean?hasNoUserSuppliedProxyInterfaces(AdvisedSupport?config)?{
????????Class>[]?ifcs?=?config.getProxiedInterfaces();
????????return?(ifcs.length?==?0?||?(ifcs.length?==?1?&&?SpringProxy.class.isAssignableFrom(ifcs[0])));
????}
}
getProxy方法分析
從對(duì)createAopProxy方法的分析可以看到,我們要么執(zhí)行的是ObjenesisCglibAopProxy中的getProxy方法,要么就是JdkDynamicAopProxy的getProxy方法,二者的區(qū)別在于一個(gè)是通過cglib的方式生成代理對(duì)象,而后者則是通過jdk的方式生成動(dòng)態(tài)代理。
這里我只分析一個(gè)JdkDynamicAopProxy,首先我們來看看這個(gè)類的繼承關(guān)系
?希望你之前已經(jīng)閱讀過
原創(chuàng) 動(dòng)態(tài)代理學(xué)習(xí)(一)自己動(dòng)手模擬JDK動(dòng)態(tài)代理
原創(chuàng) 動(dòng)態(tài)代理學(xué)習(xí)(二)JDK動(dòng)態(tài)代理源碼分析
”

可以看到這個(gè)類本身就是一個(gè)InvocationHandler,這意味著當(dāng)調(diào)用代理對(duì)象中的方法時(shí),最終會(huì)調(diào)用到JdkDynamicAopProxy的invoke方法。
所以對(duì)于這個(gè)類我們起碼應(yīng)該關(guān)注兩個(gè)方法
getProxy方法invoke方法
getProxy方法源碼如下:
public?Object?getProxy(@Nullable?ClassLoader?classLoader)?{
????if?(logger.isDebugEnabled())?{
????????logger.debug("Creating?JDK?dynamic?proxy:?target?source?is?"?+?this.advised.getTargetSource());
????}
????//?這里獲取到代理類需要實(shí)現(xiàn)的所有的接口
????Class>[]?proxiedInterfaces?=?AopProxyUtils.completeProxiedInterfaces(this.advised,?true);
????//?需要明確是否在接口定義了hashCode以及equals方法
????//?如果接口中沒有定義,那么在調(diào)用代理對(duì)象的equals方法的時(shí)候
????//?如果兩個(gè)對(duì)象相等,那么意味著它們的目標(biāo)對(duì)象,通知以及實(shí)現(xiàn)的接口都相同
????findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
????return?Proxy.newProxyInstance(classLoader,?proxiedInterfaces,?this);
}
我們?cè)賮砜纯吹降资窃趺传@取到需要實(shí)現(xiàn)的接口的
static?Class>[]?completeProxiedInterfaces(AdvisedSupport?advised,?boolean?decoratingProxy)?{
????//?第一步:獲取在配置中指定的需要實(shí)現(xiàn)的接口
????Class>[]?specifiedInterfaces?=?advised.getProxiedInterfaces();
????
????//?第二步:如果沒有指定需要實(shí)現(xiàn)的接口,但是需要代理的目標(biāo)類本身就是一個(gè)接口
????//?那么將其添加到代理類需要實(shí)現(xiàn)的接口的集合中
????//?如果目標(biāo)類本身不是一個(gè)接口,但是是經(jīng)過jdk代理后的一個(gè)類
????//?那么獲取這個(gè)代理后的類所有實(shí)現(xiàn)的接口,并添加到需要實(shí)現(xiàn)的接口集合中
????if?(specifiedInterfaces.length?==?0)?{
????????Class>?targetClass?=?advised.getTargetClass();
????????if?(targetClass?!=?null)?{
????????????if?(targetClass.isInterface())?{
????????????????advised.setInterfaces(targetClass);
????????????}
????????????else?if?(Proxy.isProxyClass(targetClass))?{
????????????????advised.setInterfaces(targetClass.getInterfaces());
????????????}
????????????specifiedInterfaces?=?advised.getProxiedInterfaces();
????????}
????}
????
????//?第三步:為代理類添加三個(gè)默認(rèn)需要實(shí)現(xiàn)的接口,分別是
????//?1.SpringProxy,一個(gè)標(biāo)記接口,代表這個(gè)類是通過Spring的AOP代理生成的
????//?2.Advised,提供了管理通知的方法
????//?3.DecoratingProxy,用戶獲取到真實(shí)的目標(biāo)對(duì)象
????//?這個(gè)真實(shí)對(duì)象指的是在嵌套代理的情況下會(huì)獲取到最終的目標(biāo)對(duì)象
????//?而不是指返回這個(gè)ProxyFactory的target
????boolean?addSpringProxy?=?!advised.isInterfaceProxied(SpringProxy.class);
????boolean?addAdvised?=?!advised.isOpaque()?&&?!advised.isInterfaceProxied(Advised.class);
????boolean?addDecoratingProxy?=?(decoratingProxy?&&?!advised.isInterfaceProxied(DecoratingProxy.class));
????int?nonUserIfcCount?=?0;
????if?(addSpringProxy)?{
????????nonUserIfcCount++;
????}
????if?(addAdvised)?{
????????nonUserIfcCount++;
????}
????if?(addDecoratingProxy)?{
????????nonUserIfcCount++;
????}
????Class>[]?proxiedInterfaces?=?new?Class>[specifiedInterfaces.length?+?nonUserIfcCount];
????System.arraycopy(specifiedInterfaces,?0,?proxiedInterfaces,?0,?specifiedInterfaces.length);
????int?index?=?specifiedInterfaces.length;
????if?(addSpringProxy)?{
????????proxiedInterfaces[index]?=?SpringProxy.class;
????????index++;
????}
????if?(addAdvised)?{
????????proxiedInterfaces[index]?=?Advised.class;
????????index++;
????}
????if?(addDecoratingProxy)?{
????????proxiedInterfaces[index]?=?DecoratingProxy.class;
????}
????return?proxiedInterfaces;
}
invoke方法分析
在確認(rèn)了需要實(shí)現(xiàn)的接口后,直接調(diào)用了jdk的動(dòng)態(tài)代理方法,這個(gè)我們就不做分析了,接下來我們來看看Spring是如何將通知應(yīng)用到代理對(duì)象上的,對(duì)應(yīng)的要分析的代碼就是JdkDynamicAopProxy的invoke方法,源碼如下:
//?這個(gè)方法的代碼稍微有點(diǎn)長(zhǎng),代碼也比較難,希望大家能耐心看完
public?Object?invoke(Object?proxy,?Method?method,?Object[]?args)?throws?Throwable?{
????Object?oldProxy?=?null;
????boolean?setProxyContext?=?false;
????TargetSource?targetSource?=?this.advised.targetSource;
????Object?target?=?null;
????try?{
????????//?首先處理的是hashCode跟equals方法
????????//?如果接口中沒有定義這兩個(gè)方法,那么會(huì)調(diào)用本類中定義的equals方法
????????//?前面我們也說過了,只有當(dāng)兩個(gè)類的目標(biāo)對(duì)象,通知以及實(shí)現(xiàn)的接口都相等的情況下
????????//?equals才會(huì)返回true
????????//?如果接口中定義了這兩個(gè)方法,那么最終會(huì)調(diào)用目標(biāo)對(duì)象中的方法
????????if?(!this.equalsDefined?&&?AopUtils.isEqualsMethod(method))?{
????????????return?equals(args[0]);
????????}
????????else?if?(!this.hashCodeDefined?&&?AopUtils.isHashCodeMethod(method))?{
????????????return?hashCode();
????????}
????????
????????//?也就是說我們調(diào)用的是DecoratingProxy這個(gè)接口中的方法
????????//?這個(gè)接口中只定義了一個(gè)getDecoratedClass方法,用于獲取到
????????//?最終的目標(biāo)對(duì)象,在方法實(shí)現(xiàn)中會(huì)通過一個(gè)while循環(huán)來不斷接近
????????//?最終的目標(biāo)對(duì)象,直到得到的目標(biāo)對(duì)象不是一個(gè)被代理的對(duì)象才會(huì)返回
????????else?if?(method.getDeclaringClass()?==?DecoratingProxy.class)?{
????????????return?AopProxyUtils.ultimateTargetClass(this.advised);
????????}
????????
????????//?說明調(diào)用的是Advised接口中的方法,這里只是單純的進(jìn)行反射調(diào)用
????????else?if?(!this.advised.opaque?&&?method.getDeclaringClass().isInterface()?&&
?????????????????method.getDeclaringClass().isAssignableFrom(Advised.class))?{
????????????return?AopUtils.invokeJoinpointUsingReflection(this.advised,?method,?args);
????????}
????????Object?retVal;
??
????????//?說明需要將代理類暴露到線程上下文中
????????//?調(diào)用AopContext.setCurrentProxy方法將其放入到一個(gè)threadLocal中
????????if?(this.advised.exposeProxy)?{
????????????oldProxy?=?AopContext.setCurrentProxy(proxy);
????????????setProxyContext?=?true;
????????}
??
????????//?接下來就是真正的執(zhí)行代理邏輯了
????????target?=?targetSource.getTarget();
????????Class>?targetClass?=?(target?!=?null???target.getClass()?:?null);
??
????????//?先獲取整個(gè)攔截器鏈
????????List在上面整個(gè)流程中,我們抓住核心的兩步
獲取整個(gè)攔截器鏈 開始在攔截器鏈上執(zhí)行方法
我們先看第一步,對(duì)應(yīng)源碼如下:
public?List{
????MethodCacheKey?cacheKey?=?new?MethodCacheKey(method);
????Listpublic?List{
????List在構(gòu)建好攔截器鏈后,接下來就是真正執(zhí)行方法了,對(duì)應(yīng)代碼就是
//?先創(chuàng)建一個(gè)MethodInvocation
MethodInvocation?invocation?=
????new?ReflectiveMethodInvocation(proxy,?target,?method,?args,?targetClass,?chain);
//?開始在攔截器鏈上執(zhí)行這個(gè)方法
retVal?=?invocation.proceed();
最后的關(guān)鍵代碼就落在了ReflectiveMethodInvocation的proceed方法
public?Object?proceed()?throws?Throwable?{
?
????//?滿足這個(gè)條件,說明執(zhí)行到了最后一個(gè)攔截器,那么直接反射調(diào)用目標(biāo)方法
???if?(this.currentInterceptorIndex?==?this.interceptorsAndDynamicMethodMatchers.size()?-?1)?{
??????return?invokeJoinpoint();
???}
?
????//?獲取到下一個(gè)要執(zhí)行的攔截器
???Object?interceptorOrInterceptionAdvice?=
?????????this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
???if?(interceptorOrInterceptionAdvice?instanceof?InterceptorAndDynamicMethodMatcher)?{
??????//?前面構(gòu)建攔截器鏈的時(shí)候我們可以看到,動(dòng)態(tài)的攔截的話會(huì)創(chuàng)建一個(gè)InterceptorAndDynamicMethodMatcher
??????InterceptorAndDynamicMethodMatcher?dm?=
????????????(InterceptorAndDynamicMethodMatcher)?interceptorOrInterceptionAdvice;
??????if?(dm.methodMatcher.matches(this.method,?this.targetClass,?this.arguments))?{
?????????return?dm.interceptor.invoke(this);
??????}
??????else?{
????????//?如果匹配失敗了,執(zhí)行攔截器鏈中的下一個(gè)攔截邏輯
?????????return?proceed();
??????}
???}
???else?{
???//?調(diào)用攔截器中的invoke方法,可以看到這里將this作為參數(shù)傳入了
??????//?所以我們?cè)跀r截器中調(diào)用?MethodInvocation的proceed時(shí)又會(huì)進(jìn)行入當(dāng)前這個(gè)方法
??????//?然后去執(zhí)行鏈條中的下一個(gè)攔截器?
??????return?((MethodInterceptor)?interceptorOrInterceptionAdvice).invoke(this);
???}
}
總結(jié)
本文主要是為下篇文章做準(zhǔn)備,下篇文章將會(huì)結(jié)束整個(gè)IOC流程的分析,IOC的最后一步便是為Bean創(chuàng)建代理。本文已經(jīng)分析了代理的具體創(chuàng)建邏輯,在下篇文章中我們主要結(jié)合Spring的啟動(dòng)流程來看一看Spring是如何將通知添加到創(chuàng)建代理的配置信息中去的。
關(guān)于整個(gè)IOC跟AOP的模塊還會(huì)有兩篇文章,一篇用于結(jié)束整個(gè)IOC流程,另外一篇專門探討Spring中循環(huán)依賴的解決。完成這兩篇文章中,接下來打算用5到7篇文章對(duì)Spring的事務(wù)管理進(jìn)行分析!
如果我的文章能幫到你,記得點(diǎn)個(gè)贊哈~!
我叫DMZ,一個(gè)在學(xué)習(xí)路上匍匐前行的小菜鳥!
