我的问题
为了完成公司应用开发平台的设计,这几天一直在研究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类图

如以上的类图所示,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接口,它的相关类图如下:

实现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