生活随笔
收集整理的這篇文章主要介紹了
Spring AOP 的proxy详解
小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
spring 提供了多種不同的方案實(shí)現(xiàn)對(duì) bean 的 aop proxy, 包括 ProxyFactoryBean, 便利的 TransactionProxyFactoryBean 以及 AutoProxyCreator 等,
下圖是 proxy class diagram 以供參考
這里重點(diǎn)說(shuō)一下最常用的 ProxyFactoryBean, TransactionProxyFactoryBean, BeanNameAutoProxyCreator, DefaultAdvisorAutoProxyCreator 的聯(lián)系和區(qū)別
1. ProxyFactoryBean : 使用率最高的 proxy 方式, 它通過(guò)配置 interceptorNames 屬性決定加入哪些 advisor (method interceptor 將會(huì)被自動(dòng)包裝成 advisor, 下文將描述這個(gè)細(xì)節(jié)),
注意是 "interceptorNames" 而不是 "interceptors",
原因是 ProxyFactoryBean 可能返回非 singleton 的 proxy 實(shí)例, 而 advisior 可能也是非 singleton 的,
因此不能通過(guò) interceptor reference 來(lái)注入
2. TransactionProxyFactoryBean : 特定用于 transaction proxy, 注意其 super class 是 AbstractSingletonProxyFactoryBean, 也就是說(shuō),
TransactionProxyFactoryBean 永遠(yuǎn)無(wú)法返回非 singleton 的 proxy 實(shí)例 !!!
如果你需要非 singleton 的 proxy 實(shí)例, 請(qǐng)考慮使用 ProxyFactoryBean.
3. BeanNameAutoProxyCreator : 故名思義, 根據(jù) bean name 進(jìn)行 auto proxy, bean name 的 match 規(guī)則參見(jiàn) org.springframework.util.PatternMatchUtils
4. DefaultAdvisorAutoProxyCreator : 更強(qiáng)大的 auto proxy creator, 強(qiáng)大之處在于它會(huì) cahce 容器中所有注冊(cè)的 advisor, 然后搜索容器中所有的 bean ,
如果某個(gè) bean 滿足 advisor 中的 Pointcut, 那么將會(huì)被自動(dòng)代理, 與 BeanNameAutoProxyCreator 相比, 省去了配置 beanNames 的工作,
?
引用:
eg :??????
???<bean?class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"?/> ???<bean?id="defaultPointcutAdvisor"?class="org.springframework.aop.support.DefaultPointcutAdvisor"?scope="prototype"> ??????????<property?name="pointcut"?ref="fooPointcut"/> ??????????<property?name="advice"?ref="fooAdvice"/> ??</bean>??? ????<bean?id="fooAdvice"?class="com.mycompany.FooAdvice"?scope="prototype"?/> ????<bean?id="fooPointcut"?class="org.springframework.aop.support.JdkRegexpMethodPointcut"?scope="prototype"> ??????????<property?name="patterns"> ??????????????<list> ??????????????????<value>com.mycompany.FooService.*</value> ??????????????</list> ??????????</property> ??????</bean> ?????? [java] view plaincopy
???????<bean?class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"?/>???<bean?id="defaultPointcutAdvisor"?class="org.springframework.aop.support.DefaultPointcutAdvisor"?scope="prototype">??????????<property?name="pointcut"?ref="fooPointcut"/>??????????<property?name="advice"?ref="fooAdvice"/>??</bean>???????<bean?id="fooAdvice"?class="com.mycompany.FooAdvice"?scope="prototype"?/>????<bean?id="fooPointcut"?class="org.springframework.aop.support.JdkRegexpMethodPointcut"?scope="prototype">??????????<property?name="patterns">??????????????<list>??????????????????<value>com.mycompany.FooService.*</value>??????????????</list>??????????</property>??????</bean>??????
以上配置將自動(dòng)代理容器中所有 com.mycompany.FooService 類型的 bean, 并攔截其所有方法
深度話題
1. MethodInterceptor 如何被包裝成 Advisor ?
在 AdvisorAdapterRegistry#wrap(Object) 方法中實(shí)現(xiàn), code as below
public?Advisor?wrap(Object?adviceObject)?throws?UnknownAdviceTypeException?{ ????if?(adviceObject?instanceof?Advisor)?{ ??????return?(Advisor)?adviceObject; ????} ????if?(!(adviceObject?instanceof?Advice))?{ ??????hrow?new?UnknownAdviceTypeException(adviceObject); ????} ????Advice?advice?=?(Advice)?adviceObject; ????if?(advice?instanceof?MethodInterceptor)?{ ????????return?new?DefaultPointcutAdvisor(advice); ????} ????for?(int?i?=?0;?i?<?this.adapters.size();?i++)?{ ?????/?Check?that?it?is?supported. ?????????????????????????????????AdvisorAdapter?adapter?=?(AdvisorAdapter)?this.adapters.get(i); ??if?(adapter.supportsAdvice(advice))?{ ???????????????????????????????????return?new?DefaultPointcutAdvisor(advice); ???} ??} ????throw?new?UnknownAdviceTypeException(advice); ??????????????????????} ????????????? [java] view plaincopy
public?Advisor?wrap(Object?adviceObject)?throws?UnknownAdviceTypeException?{????if?(adviceObject?instanceof?Advisor)?{??????return?(Advisor)?adviceObject;????}????if?(!(adviceObject?instanceof?Advice))?{??????hrow?new?UnknownAdviceTypeException(adviceObject);????}????Advice?advice?=?(Advice)?adviceObject;????if?(advice?instanceof?MethodInterceptor)?{????????return?new?DefaultPointcutAdvisor(advice);????}????for?(int?i?=?0;?i?<?this.adapters.size();?i++)?{?????/?Check?that?it?is?supported.?????????????????????????????????AdvisorAdapter?adapter?=?(AdvisorAdapter)?this.adapters.get(i);??if?(adapter.supportsAdvice(advice))?{???????????????????????????????????return?new?DefaultPointcutAdvisor(advice);???}??}????throw?new?UnknownAdviceTypeException(advice);??????????????????????}?????????????
從代碼可以看到, 如果 adviceObject(也就是 interceptorNames 對(duì)應(yīng)的 bean) 不是 advisor
而是 MethodInterceptor 或 Advice, 那么 spring 將其包裝成 DefaultPointcutAdvisor,
而 DefaultPointcutAdvisor 中定義的 Pointcut 是 TruePointcut :
????class?TruePointcut?implements?Pointcut,?Serializable?{ ????????public?static?final?TruePointcut?INSTANCE?=?new?TruePointcut(); ?????? ??????????private?TruePointcut()?{ ??????} ????????public?ClassFilter?getClassFilter()?{ ??????????return?ClassFilter.TRUE; ??????} ????????public?MethodMatcher?getMethodMatcher()?{ ??????????return?MethodMatcher.TRUE; ??????} ?????? ??????????private?Object?readResolve()?{ ??????????return?INSTANCE; ??????} ????????public?String?toString()?{ ??????????return?"Pointcut.TRUE"; ??????} ????} ?????? ???????? [java] view plaincopy
????class?TruePointcut?implements?Pointcut,?Serializable?{????????public?static?final?TruePointcut?INSTANCE?=?new?TruePointcut();????????????????private?TruePointcut()?{??????}????????public?ClassFilter?getClassFilter()?{??????????return?ClassFilter.TRUE;??????}????????public?MethodMatcher?getMethodMatcher()?{??????????return?MethodMatcher.TRUE;??????}????????????????private?Object?readResolve()?{??????????return?INSTANCE;??????}????????public?String?toString()?{??????????return?"Pointcut.TRUE";??????}????}??????????????
也就是說(shuō), MethodInterceptor 和 Advice 被包裝成的 Advisor 將會(huì)匹配容器中的所有 bean,
所以, 永 遠(yuǎn)不要在 DefaultAdvisorAutoProxyCreator 的 interceptorNames 中引用一個(gè) Advice, 那將會(huì)使容器中所有的 bean 被自動(dòng)代理!!! 此時(shí)應(yīng)該考慮使用 BeanNameAutoProxyCreator
轉(zhuǎn)載于:https://www.cnblogs.com/hanxue112253/p/3878181.html
總結(jié)
以上是生活随笔為你收集整理的Spring AOP 的proxy详解的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。