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(连接点)程序执行过程中明确的点,如方法的调用或特定的异常被抛出。

 

 

首先明确一点,SpringBeanFactoryFactoryBean的区别,BeanFactory是类工厂,主要方法是getBean(String beanName),而对于FactoryBean而言,用户可以通过该接口的getObject方法定制实例化Bean的逻辑。

AopProxy代理对象的建立

SpringAOP模块中,一个主要的部分就是代理对象的生成,而对于Spring应用,可以看到,是通过配置和调用SpringProxyFactoryBean来完成这个任务的。在ProxyFactoryBean中封装了主要代理对象的生成过程。在这个生成过程中,可以使用JDKProxyCGLIB两种生成方式。

首先关注一下ProxyFactoryBean的类继承图


ProxyConfig提供了在创建代理过程中需要用到的配置属性。

AdvisedSupport封装了AOP对通知和通知器的相关操作,这些操作对于不同的AOP的代理对象都是一样的,但对于具体的AOP代理对象的建立,AdvisedSupport把它交给具体的子类去完成。

ProxyCreatorSupport是代理工厂的基类,具体的AOP代理对象的生成,根据需要分别由ProxyFactoryBeanAspectJProxyFactoryProxyFactory来完成。

 

下面分析一下ProxyFactoryBean是如何生成AopProxy代理对象的。下图是生成AopProxy的大概的顺序图。


首先配置ProxyFactroyBean,如下


从以上配置可以看出,ProxyFactoryBean类有两个重要的成员变量,targetinterceptorNames。其中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来完成,而是由JdkDynamicAopProxyCglibProxyFactory来完成的。

JdkDynamicAopProxy中,使用JDKProxy类来生成代理对象,首先需要从advised对象中取得代理对象的代理接口配置,然后调用ProxynewProxyInstance方法,最终得到对应的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的相关源代码。








0 0
原创粉丝点击