这两天一直在读spring1.2的AOP实现源码,AOP实现原理说起来很简单,对于实现业务接口的对象使用java代理机制实现,而对于一般的类使用cglib库实现,但spring的实现还是比较复杂的,不过抓住了本质去看代码就容易多了。发现一篇04年写的
《spring源码分析:实现AOP》,倒是不用自己再写了,04年的时候已经有很多人研读过spring的源码,而那时的我还在学校,对java半懂不懂的状态,就算到现在也不敢说真的懂了,继续学习、努力。文章如下:
我的问题
为了完成公司应用开发平台的设计,这几天一直在研究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>
</property>
</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进行判断。
分享到:
相关推荐
AOP流程源码分析-SpringAOP中定义的类图AOP流程源码分析-SpringAOP中定义的类图AOP流程源码分析-SpringAOP中定义的类图AOP流程源码分析-SpringAOP中定义的类图AOP流程源码分析-SpringAOP中定义的类图AOP流程源码分析...
《Spring AOP 源码分析》 在深入探讨Spring AOP之前,我们先要理解AOP(面向切面编程)的基本概念。AOP是一种编程范式,它将关注点分离,使得我们可以将横切关注点(如日志、事务管理、安全检查等)与业务逻辑解耦...
Maven坐标:org.springframework:spring-aop:5.0.10.RELEASE; 标签:spring、aop、springframework、jar包、java、API文档、中文版; 使用方法:解压翻译后的API文档,用浏览器打开“index.html”文件,即可纵览...
Java流行框架源码分析:Spring源码、SpringBoot源码、SpringAOP源码、SpringSecurity源码、SpringSecurity OAuth2源码、JDK源码、Netty源码
本文将深入Spring源码,探索AOP的实现原理。 首先,我们需要理解AOP的基本概念。AOP允许开发者定义“切面”(Aspect),一个切面封装了跨越多个对象的横切关注点。切点(Pointcut)定义了这些关注点在何时何地被...
Spring源码最难问题:当Spring AOP遇上循环依赖 Spring源码中最难的问题之一是循环依赖问题,当Spring AOP遇上循环依赖时,该如何解决? Spring通过三级缓存机制解决循环依赖的问题。 在Spring中,bean的实例化...
本篇文章将深入探讨如何通过Spring的注解方式实现AOP的细节。 首先,我们需要了解AOP的基本概念。AOP的核心是切面(Aspect),它封装了跨越多个对象的行为或责任。切点(Pointcut)定义了哪些方法会被通知(Advice...
- **避免过度使用AOP:**过度使用AOP可能会导致系统复杂度增加,应谨慎考虑是否真正需要引入AOP。 - **注意性能影响:**虽然AOP可以提高代码的可维护性和可扩展性,但过度使用可能会对性能产生负面影响。 #### 代码...
1. **抽象工厂模式(Abstract Factory)**:Spring AOP框架中的`AopProxyFactory`接口代表抽象工厂,如`DefaultAopProxyFactory`是其实现,负责创建代理对象。抽象工厂模式确保了客户端无需关注具体对象的创建细节,...
7. **Spring AOP中的拦截器调用实现**:Spring AOP使用Advisor和Interceptor实现拦截器链,处理方法调用前后的逻辑。MethodBeforeAdvice、AfterReturningAdvice等接口定义了拦截器的行为。 8. **Spring 驱动...
- **XML配置**:在Spring的配置文件中,可以使用<aop:config>标签来定义切面,<aop:pointcut>定义切点,<aop:advisor>定义通知,<aop:aspect>将切点和通知关联起来。 - **注解配置**:Spring 2.5引入了基于注解的...
Spring AOP 源码分析笔记 Spring AOP(Aspect-Oriented Programming)是一种编程范式,它允许开发者 modularize cross-cutting concerns,即将横切关注点模块化。AOP 使得开发者可以将一些公共的功能模块化,以便在...
Maven坐标:org.springframework:spring-aop:5.2.0.RELEASE; 标签:springframework、spring、aop、中文文档、jar包、java; 使用方法:解压翻译后的API文档,用浏览器打开“index.html”文件,即可纵览文档内容。 ...
你不仅能从本书中参透Spring框架的出色架构和设计思想,还能从Spring优雅的实现源码中一窥Java语言的精髓。本书在开篇之前对Spring的设计理念和整体架构进行了全面的介绍,能让读者从宏观上厘清Spring各个功能模块...
功能:实现AOP中异常日志管理的类
在"day39-Spring 06-Spring的AOP:带有切点的切面"这个主题中,我们将深入探讨如何在Spring中实现带有切点的切面,以及它们如何与源码和工具结合使用。 首先,理解AOP的基本概念非常重要。AOP的核心是切面(Aspect...
此外,需要在Spring的Bean配置文件中添加<aop:aspectj-autoproxy>元素以启用AspectJ注解的支持。 5. 声明AspectJ切面 要在Spring中声明AspectJ切面,需要在IOC容器中将切面声明为Bean实例。一旦在Spring IOC容器中...
3. **灵活的通知模型**:Spring AOP提供了多种类型的通知,包括around、before、after returning、after throwing等,使得开发者可以根据实际需求选择最适合的通知类型。 4. **丰富的切入点表达式语言**:Spring ...
Spring AOP基于代理实现,可以使用接口代理(JDK动态代理)或类代理(CGLIB)。 7. CGLIB: CGLIB是Spring AOP默认的代理库,用于生成目标类的子类,从而实现方法拦截。当目标类没有实现接口时,Spring会使用CGLIB...
Spring AOP提供了两种实现方式:一是基于代理(Proxy-based AOP),二是基于字节码(Bytecode-based AOP)。基于代理的方式主要是使用Java动态代理或CGLIB生成代理对象;基于字节码的实现则依赖于ASM库,如AspectJ的...