天天看點

Spring AOP源碼分析(五)Spring AOP的Cglib代理

上一篇文章介紹了spring aop的jdk動态代理的過程,這一篇文章就要介紹下spring aop的cglib代理過程,仍然是使用上一篇文章的工程案例。 

jdk動态代理是由jdkdynamicaopproxy來生成代理對象的,cglib則是由cglibaopproxy來生成代理對象的。jdkdynamicaopproxy、cglibaopproxy實作了aopproxy接口,如下: 

<a href="http://my.oschina.net/pingpangkuangmo/blog/376306#">?</a>

1

2

3

4

5

6

7

<code>public</code> <code>interface</code> <code>aopproxy {</code>

<code>    </code><code>object getproxy();</code>

<code>    </code><code>object getproxy(classloader classloader);</code>

<code>}</code>

然後詳細看下cglibproxy的代理對象的生成過程。cglibproxy、jdkdynamicaopproxy都擁有一個非常重要的屬性advisedsupport advised這個屬性包含了攔截的配置資訊,這個屬性在jdkdynamicaopproxy中已經說過了,不再詳細說明。 

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

<code>public</code> <code>object getproxy(classloader classloader) {</code>

<code>        </code><code>if</code> <code>(logger.isdebugenabled()) {</code>

<code>            </code><code>logger.debug(</code><code>"creating cglib proxy: target source is "</code> <code>+</code><code>this</code><code>.advised.gettargetsource());</code>

<code>        </code><code>}</code>

<code>        </code><code>try</code> <code>{</code>

<code>//此時的rootclass為bserviceimpl</code>

<code>            </code><code>class&lt;?&gt; rootclass =</code><code>this</code><code>.advised.gettargetclass();</code>

<code>            </code><code>assert.state(rootclass !=</code><code>null</code><code>,</code><code>"target class must be available for creating a cglib proxy"</code><code>);</code>

<code>            </code><code>class&lt;?&gt; proxysuperclass = rootclass;</code>

<code>//這裡判斷rootclass是否是cglib代理所産生的類(内部判斷rootclass的classname是否包含$$),對于本工程肯定不符合,跳過</code>

<code>            </code><code>if</code> <code>(classutils.iscglibproxyclass(rootclass)) {</code>

<code>                </code><code>proxysuperclass = rootclass.getsuperclass();</code>

<code>                </code><code>class&lt;?&gt;[] additionalinterfaces = rootclass.getinterfaces();</code>

<code>                </code><code>for</code> <code>(class&lt;?&gt; additionalinterface : additionalinterfaces) {</code>

<code>                    </code><code>this</code><code>.advised.addinterface(additionalinterface);</code>

<code>                </code><code>}</code>

<code>            </code><code>}</code>

<code>//驗證proxysuperclass中的是否有final方法(僅僅是列印出來警告資訊,不做任何處理)</code>

<code>            </code><code>// validate the class, writing log messages as necessary.</code>

<code>            </code><code>validateclassifnecessary(proxysuperclass);</code>

<code>            </code><code>// configure cglib enhancer...</code>

<code>            </code><code>enhancer enhancer = createenhancer();</code>

<code>            </code><code>if</code> <code>(classloader !=</code><code>null</code><code>) {</code>

<code>                </code><code>enhancer.setclassloader(classloader);</code>

<code>                </code><code>if</code> <code>(classloader</code><code>instanceof</code> <code>smartclassloader &amp;&amp;</code>

<code>                        </code><code>((smartclassloader) classloader).isclassreloadable(proxysuperclass)) {</code>

<code>                    </code><code>enhancer.setusecache(</code><code>false</code><code>);</code>

<code>            </code><code>enhancer.setsuperclass(proxysuperclass);</code>

<code>            </code><code>enhancer.setinterfaces(aopproxyutils.completeproxiedinterfaces(</code><code>this</code><code>.advised));</code>

<code>            </code><code>enhancer.setnamingpolicy(springnamingpolicy.instance);</code>

<code>            </code><code>enhancer.setstrategy(</code><code>new</code> <code>undeclaredthrowablestrategy(undeclaredthrowableexception.</code><code>class</code><code>));</code>

<code>            </code><code>callback[] callbacks = getcallbacks(rootclass);</code>

<code>            </code><code>class&lt;?&gt;[] types =</code><code>new</code> <code>class&lt;?&gt;[callbacks.length];</code>

<code>            </code><code>for</code> <code>(</code><code>int</code> <code>x =</code><code>0</code><code>; x &lt; types.length; x++) {</code>

<code>                </code><code>types[x] = callbacks[x].getclass();</code>

<code>            </code><code>// fixedinterceptormap only populated at this point, after getcallbacks call above</code>

<code>            </code><code>enhancer.setcallbackfilter(</code><code>new</code> <code>proxycallbackfilter(</code>

<code>                    </code><code>this</code><code>.advised.getconfigurationonlycopy(),</code><code>this</code><code>.fixedinterceptormap,</code><code>this</code><code>.fixedinterceptoroffset));</code>

<code>            </code><code>enhancer.setcallbacktypes(types);</code>

<code>            </code><code>// generate the proxy class and create a proxy instance.</code>

<code>            </code><code>return</code> <code>createproxyclassandinstance(enhancer, callbacks);</code>

<code>        </code><code>//略</code>

<code>    </code><code>}</code>

上述内容,就是使用enhancer設定下要繼承的父類、設定下要實作的接口、設定下回調然後就建立出代理對象。其中的一個重要的回調callback為dynamicadvisedinterceptor,在dynamicadvisedinterceptor的intercept方法裡面實作了和jdk動态代理同樣類似的邏輯。 

接下來我們看下這一攔截過程是如何實作的。在dynamicadvisedinterceptor的intercept方法裡: 

<code>@override</code>

<code>        </code><code>public</code> <code>object intercept(object proxy, method method, object[] args, methodproxy methodproxy)</code><code>throws</code> <code>throwable {</code>

<code>            </code><code>object oldproxy =</code><code>null</code><code>;</code>

<code>            </code><code>boolean</code> <code>setproxycontext =</code><code>false</code><code>;</code>

<code>            </code><code>class&lt;?&gt; targetclass =</code><code>null</code><code>;</code>

<code>            </code><code>object target =</code><code>null</code><code>;</code>

<code>            </code><code>try</code> <code>{</code>

<code>                </code><code>if</code> <code>(</code><code>this</code><code>.advised.exposeproxy) {</code>

<code>                    </code><code>// make invocation available if necessary.</code>

<code>                    </code><code>oldproxy = aopcontext.setcurrentproxy(proxy);</code>

<code>                    </code><code>setproxycontext =</code><code>true</code><code>;</code>

<code>                </code><code>// may be null. get as late as possible to minimize the time we</code>

<code>                </code><code>// "own" the target, in case it comes from a pool...</code>

<code>                </code><code>target = gettarget();</code>

<code>                </code><code>if</code> <code>(target !=</code><code>null</code><code>) {</code>

<code>                    </code><code>targetclass = target.getclass();</code>

<code>                </code><code>list&lt;object&gt; chain =</code><code>this</code><code>.advised.getinterceptorsanddynamicinterceptionadvice(method, targetclass);</code>

<code>                </code><code>object retval;</code>

<code>                </code><code>// check whether we only have one invokerinterceptor: that is,</code>

<code>                </code><code>// no real advice, but just reflective invocation of the target.</code>

<code>                </code><code>if</code> <code>(chain.isempty() &amp;&amp; modifier.ispublic(method.getmodifiers())) {</code>

<code>                    </code><code>// we can skip creating a methodinvocation: just invoke the target directly.</code>

<code>                    </code><code>// note that the final invoker must be an invokerinterceptor, so we know</code>

<code>                    </code><code>// it does nothing but a reflective operation on the target, and no hot</code>

<code>                    </code><code>// swapping or fancy proxying.</code>

<code>                    </code><code>retval = methodproxy.invoke(target, args);</code>

<code>                </code><code>else</code> <code>{</code>

<code>                    </code><code>// we need to create a method invocation...</code>

<code>                    </code><code>retval =</code><code>new</code> <code>cglibmethodinvocation(proxy, target, method, args, targetclass, chain, methodproxy).proceed();</code>

<code>                </code><code>retval = processreturntype(proxy, target, method, retval);</code>

<code>                </code><code>return</code> <code>retval;</code>

<code>            </code><code>finally</code> <code>{</code>

<code>                    </code><code>releasetarget(target);</code>

<code>                </code><code>if</code> <code>(setproxycontext) {</code>

<code>                    </code><code>// restore old proxy.</code>

<code>                    </code><code>aopcontext.setcurrentproxy(oldproxy);</code>

上面和jdk動态代理一樣也是分兩大步,第一步擷取一個攔截器鍊,第二步建立一個methodinvocation來執行這個攔截器鍊。 

第一步:和jdk動态代理擷取攔截器鍊的過程一樣的。 

第二步:它建立的methodinvocation是cglibmethodinvocation,它是繼承了jdk動态代理所建立的reflectivemethodinvocation,覆寫了reflectivemethodinvocation的invokejoinpoint方法。reflectivemethodinvocation的invokejoinpoint方法内容如下: 

<code>protected</code> <code>object invokejoinpoint()</code><code>throws</code> <code>throwable {</code>

<code>        </code><code>return</code> <code>aoputils.invokejoinpointusingreflection(</code><code>this</code><code>.target,</code><code>this</code><code>.method,</code><code>this</code><code>.arguments);</code>

就是利用反射進行目标方法的調用執行。 

再看下cglibmethodinvocation的invokejoinpoint方法: 

<code>            </code><code>if</code> <code>(</code><code>this</code><code>.publicmethod) {</code>

<code>                </code><code>return</code> <code>this</code><code>.methodproxy.invoke(</code><code>this</code><code>.target,</code><code>this</code><code>.arguments);</code>

<code>            </code><code>else</code> <code>{</code>

<code>                </code><code>return</code> <code>super</code><code>.invokejoinpoint();</code>

this.publicmethod就是說明所調用的方法是否是public類型的。我們來看下它的來曆: 

<code>public</code> <code>cglibmethodinvocation(object proxy, object target, method method, object[] arguments,</code>

<code>                </code><code>class&lt;?&gt; targetclass, list&lt;object&gt; interceptorsanddynamicmethodmatchers, methodproxy methodproxy) {</code>

<code>            </code><code>super</code><code>(proxy, target, method, arguments, targetclass, interceptorsanddynamicmethodmatchers);</code>

<code>            </code><code>this</code><code>.methodproxy = methodproxy;</code>

<code>            </code><code>this</code><code>.publicmethod = modifier.ispublic(method.getmodifiers());</code>

在建構cglibmethodinvocation這個methodinvocation時進行指派的。modifier.ispublic(method.getmodifiers());就是判斷該方法是否是public類型的。 

cglibmethodinvocation與reflectivemethodinvocation僅僅在執行目标方法的時候有所不同,當目标方法是public方法時,reflectivemethodinvocation一直采用反射的政策執行目标方法。而cglibmethodinvocation卻使用this.methodproxy.invoke(this.target, this.arguments)代理方法來執行。看下它的好處的描述(cglibmethodinvocation的invokejoinpoint()方法的注釋): 

<code>/**</code>

<code>         </code><code>* gives a marginal performance improvement versus using reflection to</code>

<code>         </code><code>* invoke the target when invoking public methods.</code>

<code>         </code><code>*/</code>

<code>        </code><code>@override</code>

<code>        </code><code>protected</code> <code>object invokejoinpoint()</code><code>throws</code> <code>throwable {</code>

<code>//略</code>

當執行public方法時,會比反射有一個更好的性能。然而當我們在使用cglib的callback的時候卻還是使用反射,沒有去使用methodproxy。是以我們還是按照源碼的使用方式來使用,來提升性能。 

本文章中許多步驟省略了,是因為在上一篇springaop jdk的動态代理文章中都進行了詳細介紹,同時許多的接口也在上上一篇文章springaop的接口說明中給出了詳細的說明。