Spring AOP源码解析

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring AOP源码解析相关的知识,希望对你有一定的参考价值。

以编程的方式使用spring提供的AOP功能,下面是一个简单的例子:

package com.zws.spring.core.aop.springAop;

import java.lang.reflect.Method;

import org.springframework.aop.MethodBeforeAdvice;
import org.springframework.aop.framework.ProxyFactory;

public class SpringProxyClient {

	public static void main(String[] args) {
		ProxyFactory proxy = new ProxyFactory(new SpringPojo());
		proxy.addAdvice(new PojoAdvice());
		
		SpringPojo proxyPojo = (SpringPojo) proxy.getProxy();
		proxyPojo.foo();
	}
}

class SpringPojo {
	
	public void foo() {
		System.out.println("This is SpringPojo foo");
	}
}

class PojoAdvice implements MethodBeforeAdvice{

	@Override
	public void before(Method method, Object[] args, Object target) throws Throwable {
		System.out.println("This is bar");
	}

}

这段代码最重要的一个类是ProxyFactory,此类以及相关的类的类图如下:

技术分享图片

如果想要使用AspectJ风格的AOP可以使用AspectJProxyFactory。在使用ProxyFactory生成代理对象的时候,当实例化ProxyFactory对象时就会收集代理目标对象的接口信息,源代码如下:

	public ProxyFactory(Object target) {
		setTarget(target);
		setInterfaces(ClassUtils.getAllInterfaces(target));
	}

代理目标的接口信息存放在类AdvisedSupport的interfaces属性中,此属性是一个集合,如下:

private List<Class<?>> interfaces = new ArrayList<Class<?>>();

 当然在实例化ProxyFactory对象之前Spring还会实例化一个更重要的对象:AopProxy对象,此接口才是真正产生代理对象的接口。父类ProxyCreatorSupport会保存一个AopProxyFactory类型的属性aopProxyFactory,如下:

private AopProxyFactory aopProxyFactory;

此属性会在ProxyCreatorSupport的无参构造函数中实例化,如下:

	/**
	 * Create a new ProxyCreatorSupport instance.
	 */
	public ProxyCreatorSupport() {
		this.aopProxyFactory = new DefaultAopProxyFactory();
	}

当调用ProxyFactory的getProxy()方法时首先会调用DefaultAopProxyFactory类的createAopProxy()方法产生一个AopProxy对象,此时就需要判断使用JDK的动态代理还是GCLIB的代理类产生代理对象,在条件允许的情况下Spring会首选JDK动态代理的方式,其判断逻辑为目标对象类型是接口或者其本身就已经是一个JDK动态代理生成的对象。如果不满足上面的条件就使用Cglib代理生成代理对象,其源码如下:

	@Override
	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() || Proxy.isProxyClass(targetClass)) {
				return new JdkDynamicAopProxy(config);
			}
			return new ObjenesisCglibAopProxy(config);
		}
		else {
			return new JdkDynamicAopProxy(config);
		}
	}

AopProxy对象生成后就可以直接调用其getProxy()方法产生代理对象了。AopProxyFactory接口的createAopProxy()方法屏蔽了如何选择以及选择哪种代理,对客户端而言这些都是透明的。

以上是关于Spring AOP源码解析的主要内容,如果未能解决你的问题,请参考以下文章

三:Spring-AOP源码

10. Spring AOP源码解析

Spring源码分析AOP源码解析(下篇)

做一个合格的程序猿之浅析Spring AOP源码(十八) Spring AOP开发大作战源码解析

Spring AOP源码解析

spring5 源码深度解析----- Spring事务 是怎么通过AOP实现的?(100%理解Spring事务)