1. 程式人生 > >Spring AOP源碼解析

Spring AOP源碼解析

spingaop sping 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源碼解析