探索Spring2.0中的AOP(三)
前两篇文章我们探讨了Spring2.0中的AOP的配置文件和内部实现方式。最后我们再花一点时间看看具体的AOP代理是如何生成的。
Spring的AOP实现中,代理对象是通过接口AopProxy来生成的,接口定义如下图所示:
可以看到,该接口定义的两个方法都是用来提供代理对象。如果你看过上篇文章,应该记得AopProxy是通过AdvisedSupport的方法createAopProxy产生的,在此我们在此给出AdvisedSupport的类图:
而方法createAopProxy是通过接口AopProxyFactory来获得AopProxy,其接口定义如下:
可是问题又来了,AdvisedSupport又是如何获得这个AopProxy工厂的呢,要了解这个问题,还得回顾一下ProxyBeanFactory的继承结构:
从该体系结构中,我们会发现AdvisedSupport继承了一个叫做ProxyConfig的类,原来就是该类提供了访问AopProxy工厂的功能,其定义如下:
由于AdvisedSupport继承了ProxyConfig,于是在AdvisedSupport返回AopProxy的方法createAopProxy内部首先获得了由ProxyConfig的方法getAopProxyFactory返回的AopProxyFactory,接着通过该AopProxy工厂的方法createAopProxy获得AopProxy的实例。
注意ProxyConfig的内部保存了一个AopProxyFactory的实例变量aopProxyFactory,该变量在初始化的时候就被赋予了一个DefaultAopProxyFactory的实例,AdvisedSupport最终得到的就是该实例。
最后我们看看DefaultAopProxyFactory是以什么样的策略来返回AopProxy的。该默认AopProxy工厂允许通过两种类型来创建AopProxy。一是通过Cglib来创建代理对象;另一种是通过Jdk本身的动态代理机制来创建代理对象。采用不同策略的依据是Aop中的三个参数,一是ProxyConfig中的optimize是否为true;二是ProxyConfig中的proxyTargetClass是否为true;三是AdvisedSupport中的集合interfaces是否不为空。只要三者之一满足条件,即Cglib来创建代理,反之则采用Jdk的动态代理来创建代理对象。
既然又讲到代理,我们就接着上篇中的话题,研究一下Spring中的Aop究竟是代理模式还是装饰模式。同样来看看First Head中对于代理模式的阐释:
The Proxy Pattern provides a surrogate or placeholder for another object to control access to it.
对比上篇中关于装饰模式的解释,你会发现两种模式的相似之处,无论是代理对象还是装饰对象,都要实现被代理对象或是被装饰对象的接口,这样一来,调用者就无需知道自己调用的究竟是原始对象还是代理或者装饰对象;而且这两种模式都是通过继承(inheritance)+代理(delegation)的方式实现的。而代理模式和装饰模式的主要区别在于他们的目的不同。装饰模式的主要作用是为基类添加新的功能,而这些新的功能又不是所有子类所共有的,因此避免了采用继承而导致产生大量子类的状况发生;而代理模式主要的目的就如Head First所说,是为了实现访问控制,在此特例中还有一个细微的差别就是代理是通过运行时动态产生的,而装饰对象是预先生成的。
分析到此,我们心中已有定见,究竟是代理模式还是装饰模式,主要是看我们设计的出发点,如果仅仅是为了给被代理对象添加新的功能,那么可以理解为是装饰模式;而如果我们的目的是为了对代理对象中的方法做一些权限的判断和访问控制,则大可理解为是代理模式。其实设计模式的初衷就是为了解决相同模式的复杂问题,就如同练习武功,但凡武林高手都不会拘泥于武功套路,正所谓无招胜有招。但如果你只是个初入江湖的后生晚辈,那仍需对各种模式的套路强加练习,假以时日定能对这设计模式运用自如,达到出神入化的地步。
The End.