Spring AOP框架学习笔记(1):AOP代理对象的建立
来源:互联网 发布:2017中国大气污染数据 编辑:程序博客网 时间:2024/06/07 12:49
Aop的几个概念:
1.Advice(通知)定义在连接点做什么,为切面增强提供织入接口。在Spring AOP中,主要描述Spring AOP围绕方法调用而注入的切面行为。下图是Advice的类层次图。
2.Pointcut(切点)决定Advice通知应该作用于哪个连接点,也就是说通过Pointcut来定义需要增强方法的集合。
3.Advisor(通知器)用来完成对目标方法的切面增强设计(Advice)和关注点设计(Pointcut)的结合。
4.Joinpoint(连接点)程序执行过程中明确的点,如方法的调用或特定的异常被抛出。
首先明确一点,Spring中BeanFactory和FactoryBean的区别,BeanFactory是类工厂,主要方法是getBean(String beanName),而对于FactoryBean而言,用户可以通过该接口的getObject方法定制实例化Bean的逻辑。
AopProxy代理对象的建立
在Spring的AOP模块中,一个主要的部分就是代理对象的生成,而对于Spring应用,可以看到,是通过配置和调用Spring的ProxyFactoryBean来完成这个任务的。在ProxyFactoryBean中封装了主要代理对象的生成过程。在这个生成过程中,可以使用JDK的Proxy和CGLIB两种生成方式。
首先关注一下ProxyFactoryBean的类继承图
ProxyConfig提供了在创建代理过程中需要用到的配置属性。
AdvisedSupport封装了AOP对通知和通知器的相关操作,这些操作对于不同的AOP的代理对象都是一样的,但对于具体的AOP代理对象的建立,AdvisedSupport把它交给具体的子类去完成。
ProxyCreatorSupport是代理工厂的基类,具体的AOP代理对象的生成,根据需要分别由ProxyFactoryBean、AspectJProxyFactory和ProxyFactory来完成。
下面分析一下ProxyFactoryBean是如何生成AopProxy代理对象的。下图是生成AopProxy的大概的顺序图。
首先配置ProxyFactroyBean,如下
从以上配置可以看出,ProxyFactoryBean类有两个重要的成员变量,target和interceptorNames。其中target正是需要进行AOP代理的对象,而interceptorNames则定义好了通知器Advisor。
从FactoryBean获取对象,是以getObject()方法作为入口完成的,对ProxyFactoryBean来说,需要把target目标对象增加的增强处理,都通过getObject方法进行封装。如下代码所示,getObject方法首先对通知器链进行初始化,通知器链封装了一系列的拦截器,这些拦截器都要从配置中读取,然后为代理对象的生成做好准备。
public Object getObject() throws BeansException {initializeAdvisorChain();//初始化Advisor链,在后续的文章中,我们将会来详细介绍通知器的配置if (isSingleton()) {return getSingletonInstance();}else {if (this.targetName == null) {logger.warn("Using non-singleton proxies with singleton targets is often undesirable. " +"Enable prototype proxies by setting the 'targetName' property.");}return newPrototypeInstance();}}
private synchronized Object getSingletonInstance() {if (this.singletonInstance == null) {this.targetSource = freshTargetSource();if (this.autodetectInterfaces && getProxiedInterfaces().length == 0 && !isProxyTargetClass()) {// Rely on AOP infrastructure to tell us what interfaces to proxy.Class targetClass = getTargetClass();if (targetClass == null) {throw new FactoryBeanNotInitializedException("Cannot determine target class for proxy");}setInterfaces(ClassUtils.getAllInterfacesForClass(targetClass, this.proxyClassLoader));}// Initialize the shared singleton instance.super.setFrozen(this.freezeProxy);this.singletonInstance = getProxy(createAopProxy());}return this.singletonInstance;}
protected Object getProxy(AopProxy aopProxy) {return aopProxy.getProxy(this.proxyClassLoader);}
这里出现了AopProxy类型的对象,Spring利用这个AopProxy接口类把Aop代理对象的实现与框架的其他部分有效地分离开来。AopProxy接口有两个子类实现,一个是Cglib2AopProxy,另一个是JdkDynamicProxy。
在ProxyCreatorSupport中可以看到,具体的AopProxy是通过AopProxyFactory来生成的。生成代理对象需要的所有信息都封装在AdvisedSupport,这个对象是生成AopProxy的输入参数。
protected final synchronized AopProxy createAopProxy() {if (!this.active) {activate();//用于激活AdivisedSupportListener}return getAopProxyFactory().createAopProxy(this);}
这里AopProxyFactory使用的是DefaultAopProxyFactory,它是在ProxyCreatorSupport中被创建的。于是问题就转换为在DefaultAopProxyFactory中,AopProxy是怎样生成的了。
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {Class targetClass = config.getTargetClass();if (targetClass == null) {throw new AopConfigException("TargetSource cannot determine target class: " +"Either an interface or a target is required for proxy creation.");}if (targetClass.isInterface()) {<strong>return new JdkDynamicAopProxy(config);</strong>}if (!cglibAvailable) {throw new AopConfigException("Cannot proxy target class because CGLIB2 is not available. " +"Add CGLIB to the class path or specify proxy interfaces.");}<strong>return CglibProxyFactory.createCglibProxy(config);</strong>}else {return new JdkDynamicAopProxy(config);}}
从这段代码可以看出,对于具体的AopProxy对象的生成,最终并没有由DefaultAopProxyFactory来完成,而是由JdkDynamicAopProxy和CglibProxyFactory来完成的。
在JdkDynamicAopProxy中,使用JDK的Proxy类来生成代理对象,首先需要从advised对象中取得代理对象的代理接口配置,然后调用Proxy的newProxyInstance方法,最终得到对应的Proxy代理对象。
public Object getProxy(ClassLoader classLoader) {if (logger.isDebugEnabled()) {logger.debug("Creating JDK dynamic proxy: target source is " + this.advised.getTargetSource());}Class[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised);findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);}
CGLIB生成AopProxy代理对象的过程,这里就不进行分析了,有兴趣的读者可以查看Spring的相关源代码。
- Spring AOP框架学习笔记(1):AOP代理对象的建立
- 学习笔记--代理与AOP及实现类似SPRING的可配置的AOP框架
- Spring AOP的实现之建立AopProxy代理对象
- Spring AOP框架学习笔记(2):AOP拦截器调用的实现
- Spring学习笔记:使用代理实现AOP
- [Spring]Spring AOP学习笔记(1)
- Spring AOP 代理对象的生成 part3
- Spring Aop原理分析(一) - 建立AopProxy代理对象
- Spring AOP学习笔记(1):AOP基础知识
- Spring学习笔记之aop动态代理(3)
- Spring:AOP(一)生成代理对象
- spring生成代理对象的过程(AOP切面)
- Spring的AOP学习笔记
- Spring框架学习【创建AOP代理对象并对目标对象切面拦截】
- Spring-AOP 前置代理对象
- Spring Aop源码学习--Aop代理AopProxy
- Spring AOP代理的学习案例
- Spring源码分析----建立AopProxy代理对象和AOP拦截器的调用
- 自定义控件其实很简单1/2
- More is better--hdu1856(并查集)
- 小希的迷宫--hdu1272(并查集)
- 畅通工程--hdu1232(并查集)
- How Many Tables--hdu1213(并查集)
- Spring AOP框架学习笔记(1):AOP代理对象的建立
- 通过 XtraBackup 实现不停机不锁表搭建主从同步
- Ice_cream's world I--hdu2120
- Pie--hdu1969(二分法)
- crontab任务不能执行
- Cable master--hdu1551(二分法)
- ZOJ问题--hdu3788
- C++ Primer 5e chapter 6
- C++多线程编程入门2