1. 程式人生 > >【知識庫】--spring aop 動態代理--inner private protected 方法失效(212)

【知識庫】--spring aop 動態代理--inner private protected 方法失效(212)

私有方法或者保護的方法無效!

AspectJ pointcut for annotated PRIVATE methods



Due to the proxy-based nature of Spring's AOP framework, protected methods are by definition not intercepted,
neither for JDK proxies (where this isn't applicable) nor for CGLIB proxies (where this is technically possible
but not recommendable for AOP purposes). As a consequence, any given pointcut will be matched against public methods only!


If your interception needs include protected/private methods or even constructors, consider the use of Spring-driven native 
AspectJ weaving instead of Spring's proxy-based AOP framework. This constitutes a different mode of AOP usage with different 

characteristics, so be sure to make yourself familiar with weaving first before making a decision.

下文解釋:

Spring AOP使用JDK動態代理或者CGLIB來為目標物件建立代理。(建議優先使用JDK的動態代理)

如果被代理的目標物件實現了至少一個介面,則會使用JDK動態代理。所有該目標型別實現的介面都將被代理。 若該目標物件沒有實現任何介面,則建立一個CGLIB代理。

如果你希望強制使用CGLIB代理,(例如:希望代理目標物件的所有方法,而不只是實現自介面的方法) 那也可以。但是需要考慮以下問題: 

  • 無法通知(advise)final方法,因為他們不能被覆寫。

  • 代理物件的構造器會被呼叫兩次。因為在CGLIB代理模式下每一個代理物件都會 產生一個子類。每一個代理例項會生成兩個物件:實際代理物件和它的一個實現了通知的子類例項 而是用JDK代理時不會出現這樣的行為。通常情況下,呼叫代理型別的構造器兩次並不是問題, 因為除了會發生指派外沒有任何真正的邏輯被實現。
  • 且CGLib的效率沒有使用JDK代理機制高,速度平均要慢8倍左右。

強制使用CGLIB代理需要將<aop:config>的proxy-target-class屬性設為true:
<aop:config proxy-target-class="true">

</aop:config>
當使用@AspectJ自動代理時要強制使用CGLIB,請將<aop:aspectj-autoproxy>的proxy-target-class屬性設定為true:
<aop:aspectj-autoproxy proxy-target-class="true"/>

 inner public方法無效

原因其實就是一句話:Spring AOP是基於代理機制的.

具體文件參考:

http://docs.spring.io/spring/docs/3.1.x/spring-framework-reference/html/aop.html#aop-introduction-spring-defn