Spring AOP(六)【源码分析】Spring中CgLib动态代理的实现

第二类:【CgLib代理】

有关CgLib的代理实现,过程中有一个接口MethodInterceptor,在CgLib包与AOP alliance中都有定义,而意义却完全不同,文中加以了标记区分。

CgLib代理使用Demo

首先我们先来实现一个不依赖Spring框架的,单纯基于Cglib的AOP代理:
目标类:

@Component
public class TestAopTarget {

    public void process() {
        System.out.println("TestAopTarget.process()");
    }
}

自定义的MethodInterceptor:

public class MyMethodIncerceptor implements MethodInterceptor {

    /*
       Object o:要增强的目标对象
       Method method:拦截的方法
       Object[] objects:参数列表
       MethodProxy:对方法的代理
     */
    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        System.out.println("_____before");
        Object result = methodProxy.invokeSuper(o, objects);
        System.out.println("_____after");
        return result;

    }
}

测试类:

public static void main(final String[] args) {
        ApplicationContext ac = new ClassPathXmlApplicationContext("spring/applicationContext.xml");
   		//不依赖Spring的CgLib模式动态代理
        Enhancer enhancer = new Enhancer();
        //setSuperclass:设置要代理的类
        enhancer.setSuperclass(TestAopTarget.class);
        //setCallback:设置回调即MethodInterceptor的实现类
        enhancer.setCallback(new MyMethodIncerceptor());
        //create():生成一个代理对象
        TestAopTarget testAopTarget = (TestAopTarget) enhancer.create();
        testAopTarget.process();
    }

输出结果:

_____before
TestAopTarget.process()
_____after

CgLib中AOP的实现是基于org.springframework.cglib.proxy包中Enhancer和MethodInterceptor(是CgLib包中的,不是AOP alliance中的同名接口)两个接口来实现的。

对于整个过程,我们可以概括为:

  • 定义自定义的MethodInterceptor(其实现的intercept方法中是AOP具体的逻辑)
  • 创建Enhance、设置Callback为上述MethodInterceptor
  • enhancer.create()创建代理

Spring框架中CgLib代理源码分析

在得到Advisors之后,通过proxyFactory.getProxy获取代理

public Object getProxy(ClassLoader classLoader) {
		return createAopProxy().getProxy(classLoader);
	}

假定createAopProxy中决定的实现类为ObjenesisCglibAopProxy

class ObjenesisCglibAopProxy extends CglibAopProxy 

这次我们从getProxy开始看起

getProxy获取代理

此方法是在ObjenesisCglibAopProxy的父类CglibAopProxy中实现的

@Override
	public Object getProxy(ClassLoader classLoader) {
		if (logger.isDebugEnabled()) {
			logger.debug("Creating CGLIB proxy: target source is " + this.advised.getTargetSource());
		}

		try {
			Class<?> rootClass = this.advised.getTargetClass();
			Assert.state(rootClass != null, "Target class must be available for creating a CGLIB proxy");

			Class<?> proxySuperClass = rootClass;
			if (ClassUtils.isCglibProxyClass(rootClass)) {
				proxySuperClass = rootClass.getSuperclass();
				Class<?>[] additionalInterfaces = rootClass.getInterfaces();
				for (Class<?> additionalInterface : additionalInterfaces) {
					this.advised.addInterface(additionalInterface);
				}
			}

			// Validate the class, writing log messages as necessary.
			validateClassIfNecessary(proxySuperClass, classLoader);

			// Configure CGLIB Enhancer...
			Enhancer enhancer = createEnhancer();
			if (classLoader != null) {
				enhancer.setClassLoader(classLoader);
				if (classLoader instanceof SmartClassLoader &&
						((SmartClassLoader) classLoader).isClassReloadable(proxySuperClass)) {
					enhancer.setUseCache(false);
				}
			}
			enhancer.setSuperclass(proxySuperClass);
			enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));
			enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
			enhancer.setStrategy(new ClassLoaderAwareUndeclaredThrowableStrategy(classLoader));

			Callback[] callbacks = getCallbacks(rootClass);
			Class<?>[] types = new Class<?>[callbacks.length];
			for (int x = 0; x < types.length; x++) {
				types[x] = callbacks[x].getClass();
			}
			// fixedInterceptorMap only populated at this point, after getCallbacks call above
			enhancer.setCallbackFilter(new ProxyCallbackFilter(
					this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset));
			enhancer.setCallbackTypes(types);

			// Generate the proxy class and create a proxy instance.
			return createProxyClassAndInstance(enhancer, callbacks);
		}
		catch (CodeGenerationException ex) {
			throw new AopConfigException("Could not generate CGLIB subclass of class [" +
					this.advised.getTargetClass() + "]: " +
					"Common causes of this problem include using a final class or a non-visible class",
					ex);
		}
		catch (IllegalArgumentException ex) {
			throw new AopConfigException("Could not generate CGLIB subclass of class [" +
					this.advised.getTargetClass() + "]: " +
					"Common causes of this problem include using a final class or a non-visible class",
					ex);
		}
		catch (Exception ex) {
			// TargetSource.getTarget() failed
			throw new AopConfigException("Unexpected AOP exception", ex);
		}
	}

方法包含的步骤:

  • 准备及验证工作
    1. 获取目标类的全部接口
    2. 检查目标类中是否含有final修饰的方法
  • 创建及配置Enhancer
Enhancer enhancer = createEnhancer();
  • 获取拦截器链Callback
Callback[] callbacks = getCallbacks(rootClass);
  • 生成代理类并创建代理(设置enhancer的callback值)
return createProxyClassAndInstance(enhancer, callbacks)

这个过程已经实现了我们上述总结的三个步骤:

定义自定义的MethodInterceptor(其实现的intercept方法中是AOP具体的逻辑)
创建Enhance、设置Callback为上述MethodInterceptor
enhancer.create()创建代理

需要关注的过程:

  1. getCallbacks获取拦截器链
  2. createProxyClassAndInstance获取代理

1.getCallbacks获取MethodInterceptor拦截器(CgLib包中接口)链并包装为Callback

private Callback[] getCallbacks(Class<?> rootClass) throws Exception {
		// Parameters used for optimisation choices...
		boolean exposeProxy = this.advised.isExposeProxy();
		boolean isFrozen = this.advised.isFrozen();
		boolean isStatic = this.advised.getTargetSource().isStatic();

		// Choose an "aop" interceptor (used for AOP calls).
		Callback aopInterceptor = new DynamicAdvisedInterceptor(this.advised);

		// Choose a "straight to target" interceptor. (used for calls that are
		// unadvised but can return this). May be required to expose the proxy.
		Callback targetInterceptor;
		if (exposeProxy) {
			targetInterceptor = isStatic ?
					new StaticUnadvisedExposedInterceptor(this.advised.getTargetSource().getTarget()) :
					new DynamicUnadvisedExposedInterceptor(this.advised.getTargetSource());
		}
		else {
			targetInterceptor = isStatic ?
					new StaticUnadvisedInterceptor(this.advised.getTargetSource().getTarget()) :
					new DynamicUnadvisedInterceptor(this.advised.getTargetSource());
		}

		// Choose a "direct to target" dispatcher (used for
		// unadvised calls to static targets that cannot return this).
		Callback targetDispatcher = isStatic ?
				new StaticDispatcher(this.advised.getTargetSource().getTarget()) : new SerializableNoOp();

		Callback[] mainCallbacks = new Callback[] {
				aopInterceptor,  // for normal advice
				targetInterceptor,  // invoke target without considering advice, if optimized
				new SerializableNoOp(),  // no override for methods mapped to this
				targetDispatcher, this.advisedDispatcher,
				new EqualsInterceptor(this.advised),
				new HashCodeInterceptor(this.advised)
		};

		Callback[] callbacks;

		// If the target is a static one and the advice chain is frozen,
		// then we can make some optimisations by sending the AOP calls
		// direct to the target using the fixed chain for that method.
		if (isStatic && isFrozen) {
			Method[] methods = rootClass.getMethods();
			Callback[] fixedCallbacks = new Callback[methods.length];
			this.fixedInterceptorMap = new HashMap<String, Integer>(methods.length);

			// TODO: small memory optimisation here (can skip creation for methods with no advice)
			for (int x = 0; x < methods.length; x++) {
				List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(methods[x], rootClass);
				fixedCallbacks[x] = new FixedChainStaticTargetInterceptor(
						chain, this.advised.getTargetSource().getTarget(), this.advised.getTargetClass());
				this.fixedInterceptorMap.put(methods[x].toString(), x);
			}

			// Now copy both the callbacks from mainCallbacks
			// and fixedCallbacks into the callbacks array.
			callbacks = new Callback[mainCallbacks.length + fixedCallbacks.length];
			System.arraycopy(mainCallbacks, 0, callbacks, 0, mainCallbacks.length);
			System.arraycopy(fixedCallbacks, 0, callbacks, mainCallbacks.length, fixedCallbacks.length);
			this.fixedInterceptorOffset = mainCallbacks.length;
		}
		else {
			callbacks = mainCallbacks;
		}
		return callbacks;
	}

方法中:

  1. 将Advisor包装为DynamicAdvisedInterceptor
Callback aopInterceptor = new DynamicAdvisedInterceptor(this.advised);
  1. 通过DynamicAdvisedInterceptor创建CallBack
Callback[] mainCallbacks = new Callback[] {
				aopInterceptor,  // for normal advice
				targetInterceptor,  // invoke target without considering advice, if optimized
				new SerializableNoOp(),  // no override for methods mapped to this
				targetDispatcher, this.advisedDispatcher,
				new EqualsInterceptor(this.advised),
				new HashCodeInterceptor(this.advised)
		};
  1. 默认情况下isStatic && isFrozen为false,返回step 2 中callbacks;

重点在第1步:创建DynamicAdvisedInterceptor

1.1 创建MethodInterceptor(CgLIb包中的接口)

首先,DynamicAdvisedInterceptor类实现了MethodIntercepto

private static class DynamicAdvisedInterceptor implements MethodInterceptor, Serializable

那么其中一定会有intercept方法的实现,就是AOP具体的逻辑:

@Override
		public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
			Object oldProxy = null;
			boolean setProxyContext = false;
			Class<?> targetClass = null;
			Object target = null;
			try {
				if (this.advised.exposeProxy) {
					// Make invocation available if necessary.
					oldProxy = AopContext.setCurrentProxy(proxy);
					setProxyContext = true;
				}
				// May be null. Get as late as possible to minimize the time we
				// "own" the target, in case it comes from a pool...
				target = getTarget();
				if (target != null) {
					targetClass = target.getClass();
				}
				List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
				Object retVal;
				// Check whether we only have one InvokerInterceptor: that is,
				// no real advice, but just reflective invocation of the target.
				if (chain.isEmpty() && Modifier.isPublic(method.getModifiers())) {
					// We can skip creating a MethodInvocation: just invoke the target directly.
					// Note that the final invoker must be an InvokerInterceptor, so we know
					// it does nothing but a reflective operation on the target, and no hot
					// swapping or fancy proxying.
					Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
					retVal = methodProxy.invoke(target, argsToUse);
				}
				else {
					// We need to create a method invocation...
					retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();
				}
				retVal = processReturnType(proxy, target, method, retVal);
				return retVal;
			}
			finally {
				if (target != null) {
					releaseTarget(target);
				}
				if (setProxyContext) {
					// Restore old proxy.
					AopContext.setCurrentProxy(oldProxy);
				}
			}
		}

1.1.1 intercept()中:获取MethodInterceptor拦截器链(AOP alliance中的接口)

List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);

Spring AOP(五)【源码分析】Spring中JDK动态代理及其链式增强的实现1.2.1通过Advisors中的Advice获取(包装为)MethodInterceptor拦截器链(AOP alliance中的接口) ,描述了如何根据Advice获取MethodInterceptor。

1.1.2 intercept()中:创建一个MethodInvocation并调用proceed()

retVal = 
	new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy)
	.proceed();

CglibMethodInvocation类继承了ReflectiveMethodInvocation,可见它也是实现了AOP联盟中的MethodInvocation接口

private static class CglibMethodInvocation extends ReflectiveMethodInvocation

同样的,也是step1中的MethodInterceptor调用其proceed()表示执行当前拦截点。
这个过程与JDK中的相同,也是链式调用拦截点,可参考Spring AOP(五)【源码分析】Spring中JDK动态代理及其链式增强的实现中 1.2.3.2 执行MethodInvocation.proceed

1.1.3. 返回此MethodInvocation

2. createProxyClassAndInstance获取代理

这个方法是在子类ObjenesisCglibAopProxy中实现的:

protected Object createProxyClassAndInstance(Enhancer enhancer, Callback[] callbacks) {
		Class<?> proxyClass = enhancer.createClass();
		Object proxyInstance = null;

		if (objenesis.isWorthTrying()) {
			try {
				proxyInstance = objenesis.newInstance(proxyClass, enhancer.getUseCache());
			}
			catch (Throwable ex) {
				logger.debug("Unable to instantiate proxy using Objenesis, " +
						"falling back to regular proxy construction", ex);
			}
		}

		if (proxyInstance == null) {
			// Regular instantiation via default constructor...
			try {
				proxyInstance = (this.constructorArgs != null ?
						proxyClass.getConstructor(this.constructorArgTypes).newInstance(this.constructorArgs) :
						proxyClass.newInstance());
			}
			catch (Throwable ex) {
				throw new AopConfigException("Unable to instantiate proxy using Objenesis, " +
						"and regular proxy instantiation via default constructor fails as well", ex);
			}
		}

		((Factory) proxyInstance).setCallbacks(callbacks);
		return proxyInstance;
	}

方法中做了两件事:

  1. 通过Enhancer创建代理实例
  2. 将实例设置回调:传入的callback参数
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值