天天看点

Spring源码分析:实现AOP(转载)

我的问题

       为了完成公司应用开发平台的设计,这几天一直在研究spring的扩展机制。spring的核心无疑是beanfactory, applicationcontext和aop。在“spring aop编程”教程的例子中,是由proxyfactorybean来实现的。问题来了,普通的bean和factorybean的配置完全是一样的。那 么,beanfactory是如何区分普通的bean和用作proxy的factorybean的?proxyfactorybean又是怎样实现aop 功能的?(本文还很不完善,我会继续修改。)

factorybean的职责

        factorybean在spring中被当成一种特殊的bean,通过实现factorybean接口进行扩展。factorybean的职责是:

        l.封装了创建对象或查找对象的逻辑。

       2.提供了一个中间层,用于支持aop。

       我们来看一个localstatelesssessionproxyfactorybean的例子。首先,定义stateless ejb的代理,id为ejbserviceproxy:

       <bean id="ejbserviceproxy" class="localstatelesssessionproxyfactorybean">

           <property name="jndiname">     

              <value>myejb</value>

           </property>

           <property name="businessinterface">

              <value>com.mycompany.mybusinessinterface</value>

      </bean>

      然后,再将这个业务逻辑服务对象注入客户程序:

     <bean id="myaction" class = "samples.myaction">

         <property name="myservice">

             <ref bean="ejbserviceproxy"/>

         </property>

     </bean>

     这样,客户程序并不知道myservice的实现细节,spring使用factorybean完成了两者之间的解耦。

准备代码分析环境

     1. 安装eclipse和spring ide。

     2. 下载spring framework源代码,并导入eclipse。

     3. 在类路径创建log4j.properties配置文件,设置如下:

             log4j.rootlogger=debug, stdout

             log4j.appender.stdout=org.apache.log4j.consoleappender

             log4j.appender.stdout.layout=org.apache.log4j.patternlayout

             log4j.appender.stdout.layout.conversionpattern=%d{sss} %p %c{2} - %m%n

     4. 编写testcase,跟踪console窗口的debug信息。

factorybean源代码分析

       如果bean实现了factorybean接口,beanfactory将把它作为一个bean工厂,而不是直接作为普通的bean。正常情况下, beanfactory的getbean("bean")返回factorybean生产的bean实例,如果要返回factorybean本身的实例, 使用getbean("&bean")的调用方式。

       在分析proxyfactorybean之前,我们先分析beanfactory,它是spring framework的基础。我们看看它是如何分别处理普通的bean和factorybean的。

  beanfactory分析

     beanfactory类图

Spring源码分析:实现AOP(转载)

       如以上的类图所示,xmlbeanfactory继承了abstactbeanfactory抽象类。abstactbeanfactory类中使用了 template method设计模式,其中的模板方法为getbeandefinition()和createbean()两个抽象方法。其中 abstractautowirecapablebeanfactory类实现了getbeandefinition()方法, defaultautowirecapablebeanfactory类实现了getbeandefinition()方法。当调用getbean()方 法时,abstractbeanfactory类定义的逻辑分别调用了这两个模板方法。

     beanfactory类的调用顺序

       我们暂时不使用applicationcontext,以简化分析过程。我在这里使用了“spring aop编程”的例子,请参照该教程阅读。首先,编写测试用例,代码如下:

            public class aoptest extends testcase {

                  xmlbeanfactory factory = null;

                  protected void setup() throws exception {

                       super.setup();

                       inputstream is = new fileinputstream("testaop.xml");

                       factory = new xmlbeanfactory(is);

                  }

                  public void testgetbean() {

                       bean bean = (bean)factory.getbean("bean");

                       assertnotnull(bean);

                       bean.themethod();

                  }

            }

       1. 首先,xmlbeanfactory使用xmlbeandefinitionreader读入testaop.xml配置文件,后者用 xmlbeandefinitionparser和defaultxmlbeandefinitionparser进行分析,从中得到 beandefinition的信息,并保存在xmlbeandefinitionreader的beandefinitionregistry变量里。

       2. 客户程序调用getbean方法时,abstractbeanfactory首先使用transformedbeanname方法分析传入的bean名称,判断客户程序需要factorybean本身,还是它所创建的bean对象。

       3. 接下来,如果bean被定义为singleton模式,abstractbeanfactory调用createbean方法根据 beandefinition信息实例化bean类,然后将该bean实例传给getobjectforsharedinstance方法并返回 getobjectforsharedinstance的返回对象。getobjectforsharedinstance方法摘要如类图所示,首先判断 bean是否继承了factorybean。如果是,返回factorybean的getobject方法(下节我将详细分析使用 proxyfactorybean如何实现aop);如果不是,返回bean对象。

       4. 如果bean被定义为prototype模式,每次客户程序请求都会生成新的bean实例,因此,createbean方法直接实例化bean对象并返回。

  proxyfactorybean如何实现aop

     proxyfactorybean类图

       factorybean接口如下图所示,共有三个方法getobject,getobjecttype,和issingleton。proxyfactorybean实现了factorybean接口,它的相关类图如下:

Spring源码分析:实现AOP(转载)

     实现aop的过程

       如上图所示,proxyfactorybean类继承了advisedsupport类,后者继承了proxyconfig类并定义了操作advisor 和interceptor的接口,以支持aop。当beanfactory实例化proxyfactorybean时,根据配置文件的定义将关于 advice,pointcut,advisor,所代理的接口和接口实现类的所有信息传给proxyfactorybean。

       当客户程序调用beanfactory的getbean方法时,proxyfactory使用jdkdynamicaopproxy实例化 beanimpl类,并用jdkdynamicaopproxy的invoke方法执行advice。至于执行advice的时机,由 proxyfactorybean调用regexpmethodpointcutadvisor进行判断。

文章转自庄周梦蝶  ,原文发布时间5.17

继续阅读