生活随笔
收集整理的這篇文章主要介紹了
Spring AOP 的proxy详解
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
spring 提供了多種不同的方案實現(xiàn)對 bean 的 aop proxy, 包括 ProxyFactoryBean, 便利的 TransactionProxyFactoryBean 以及 AutoProxyCreator 等,
下圖是 proxy class diagram 以供參考
這里重點說一下最常用的 ProxyFactoryBean, TransactionProxyFactoryBean, BeanNameAutoProxyCreator, DefaultAdvisorAutoProxyCreator 的聯(lián)系和區(qū)別
1. ProxyFactoryBean : 使用率最高的 proxy 方式, 它通過配置 interceptorNames 屬性決定加入哪些 advisor (method interceptor 將會被自動包裝成 advisor, 下文將描述這個細節(jié)),
注意是 "interceptorNames" 而不是 "interceptors",
原因是 ProxyFactoryBean 可能返回非 singleton 的 proxy 實例, 而 advisior 可能也是非 singleton 的,
因此不能通過 interceptor reference 來注入
2. TransactionProxyFactoryBean : 特定用于 transaction proxy, 注意其 super class 是 AbstractSingletonProxyFactoryBean, 也就是說,
TransactionProxyFactoryBean 永遠無法返回非 singleton 的 proxy 實例 !!!
如果你需要非 singleton 的 proxy 實例, 請考慮使用 ProxyFactoryBean.
3. BeanNameAutoProxyCreator : 故名思義, 根據(jù) bean name 進行 auto proxy, bean name 的 match 規(guī)則參見 org.springframework.util.PatternMatchUtils
4. DefaultAdvisorAutoProxyCreator : 更強大的 auto proxy creator, 強大之處在于它會 cahce 容器中所有注冊的 advisor, 然后搜索容器中所有的 bean ,
如果某個 bean 滿足 advisor 中的 Pointcut, 那么將會被自動代理, 與 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>??????
以上配置將自動代理容器中所有 com.mycompany.FooService 類型的 bean, 并攔截其所有方法
深度話題
1. MethodInterceptor 如何被包裝成 Advisor ?
在 AdvisorAdapterRegistry#wrap(Object) 方法中實現(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 對應(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";??????}????}??????????????
也就是說, MethodInterceptor 和 Advice 被包裝成的 Advisor 將會匹配容器中的所有 bean,
所以, 永 遠不要在 DefaultAdvisorAutoProxyCreator 的 interceptorNames 中引用一個 Advice, 那將會使容器中所有的 bean 被自動代理!!! 此時應(yīng)該考慮使用 BeanNameAutoProxyCreator
轉(zhuǎn)載于:https://www.cnblogs.com/hanxue112253/p/3878181.html
總結(jié)
以上是生活随笔為你收集整理的Spring AOP 的proxy详解的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。