Spring源码阅读 —— 一文看懂AOP的流程

本文深入探讨Spring AOP的工作原理,包括基于JDK动态代理和CGLIB动态代理的实现流程,通过实例代码和配置展示前置增强、后置增强的执行过程。

  之前写过一篇关于Spring容器的文章,对于这块不清楚的童鞋可以移步浏览下。Spring Aop构建于Ioc之上,底层技术手段分别是基于接口的JDK动态代理,和基于类并为其创建子类的cglib动态代理,本文假设读者已经了解了AOP的基础知识。下面,我们将通过实例走一遍完整的流程。

目录

一. 用到的实例代码和配置

二. JDK动态代理

三. 穿插讲下 ProxyFactory

四. cglib动态代理

五. 小结



一、用到的实例代码和配置

接口


package com.example.demo.aop.advice;
/**
 * @author linxiaohui
 * @version 1.0 2018/10/23
 * @since 1.0
 */
public interface Waiter {
    void greetTo(String name);
    void serviceTo(String name);
}
复制代码

接口实现类


package com.example.demo.aop.advice;
/**
 * @author linxiaohui
 * @version 1.0 2018/10/23
 * @since 1.0
 */
public class KfcWaiter implements Waiter {
    @Override
    public void greetTo(String name) {
        System.out.println("greet to " + name);
    }
    @Override
    public void serviceTo(String name) {
        System.out.println("service to " + name);
    }
}
复制代码

前置增强


package com.example.demo.aop.advice;
import org.springframework.aop.MethodBeforeAdvice;
import java.lang.reflect.Method;
/**
 * @author linxiaohui
 * @version 1.0 2018/10/23
 * @since 1.0
 */
public class GreetBeforeAdvice implements MethodBeforeAdvice {
    @Override
    public void before(Method method, Object[] args, Object target) throws Throwable {
        System.out.println(method.getName() + "方法执行前,do something");
    }
}
复制代码

后置增强


package com.example.demo.aop.advice;
import org.springframework.aop.AfterReturningAdvice;
import java.lang.reflect.Method;
/**
 * @author linxiaohui
 * @version 1.0 2018/10/29
 * @since 1.0
 */
public class GreetAfterAdvice implements AfterReturningAdvice {
    @Override
    public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
        System.out.println(method.getName() + "方法返回后执行。。。");
    }
}
复制代码

xml配置文件

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
                           http://www.springframework.org/schema/beans/spring-beans.xsd">
    <!-- 配置一个前置增强和后置增强 -->
    <bean id="greetBeforeAdvice" class="com.example.demo.aop.advice.GreetBeforeAdvice"/>
    <bean id="grretAfterAdvice" class="com.example.demo.aop.advice.GreetAfterAdvice"/>
    <!-- 需要增强的目标类 -->
    <bean id="waiter" class="com.example.demo.aop.advice.KfcWaiter"/>
    <!-- 定义两个增强 -->
    <bean id="myAdvisor1" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
        <property name="patterns" value=".*greet.*"/>
        <property name="advice" ref="greetBeforeAdvice"/>
    </bean>
    <bean id="myAdvisor2" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
        <property name="patterns" value=".*greet.*"/>
        <property name="advice" ref="grretAfterAdvice"/>
    </bean>
    <!-- 基于Advisor自动匹配的自动代理创建器 -->
    <bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator">
        <!-- proxyTargetClass=true,使用cglib代理,默认为false -->
        <!--<property name="proxyTargetClass" value="true"/>-->
    </bean>
</beans>

复制代码

在这里我们使用DefaultAdvisorAutoProxyCreator自动创建代理。我们看下它是个什么玩意


  从图谱中我们可以看出,这货居然是个BeanPostProcessor,这是个Bean后置处理器(有需要发评论,可以出一篇描述spring容器的扩展点文章),在spring容器中有描述。执行点是在bean 实例化之后,执行 初始化操作的前后执行。(即容器执行getBean()的时候会执行)。
  下面我们从容器的启动阶段开始,到最终生成代理类执行方法结束,完整的走一遍流程,首先,我们先看下jdk动态代理。

二、JDK动态代理

  首先,贴上启动程序

package com.example.demo.aop;
import com.example.demo.aop.advice.Waiter;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
 * @author linxiaohui
 * @version 1.0 2018/10/29
 * @since 1.0
 */
public class AopSourceCodeTest {
    public static void main(String[] args) {
        //1、加载配置文件
        ApplicationContext ctx = new ClassPathXmlApplicationContext("enhancer.xml");
        //2、获取生成的代理类
        Waiter waiter = ctx.getBean("waiter", Waiter.class);
        //3、执行代理类方法,会执行对应的拦截器方法(执行增强方法)
        waiter.greetTo("tom");
    }
}
复制代码

  由于本文重点讲解AOP的流程,所以spring容器的步骤,我们就在追求精简的同时,也能希望给大家提供一个完整的流程。有不清楚的,可以回到Spring容器看下。
  启动容器,我们直接跳到refresh()-->finishBeanFactoryInitialization(beanFactory)-->beanFactory.preInstantiateSingletons(),这里我们只看主要代码(省略了一部分)


@Override
	public void preInstantiateSingletons() throws BeansException {
		if (this.logger.isDebugEnabled()) {
			this.logger.debug("Pre-instantiating singletons in " + this);
		}
                //获取配置的bean
		List beanNames = new ArrayList(this.beanDefinitionNames);

		// 循环初始化
		for (String beanName : beanNames) {
			RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
			if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
                                //如果是factoryBean的话,走这个流程(我们这里不管)
				if (isFactoryBean(beanName)) {
					final FactoryBean factory = (FactoryBean) getBean(FACTORY_BEAN_PREFIX + beanName);
					boolean isEagerInit;
					if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
						isEagerInit = AccessController.doPrivileged(new PrivilegedAction() {
							@Override
							public Boolean run() {
								return ((SmartFactoryBean) factory).isEagerInit();
							}
						}, getAccessControlContext());
					}
					else {
						isEagerInit = (factory instanceof SmartFactoryBean &&
								((SmartFactoryBean) factory).isEagerInit());
					}
					if (isEagerInit) {
						getBean(beanName);
					}
				}
				else {
                                        //普通bean走这个流程(看这里,我们重点关注这个)。
                                        //**为了流程效果,我们讲解需要增强的目标类实例化,即waiter**
					getBean(beanName);
				}
			}
		}
               .....略......
	}
复制代码

  接下来继续提供流程线路图(省略了方法参数) getBean()-->doGetBean()-->createBean()


@Override
	protected Object createBean(String beanName, RootBeanDefinition mbd, Object[] args) throws BeanCreationException {
		if (logger.isDebugEnabled()) {
			logger.debug("Creating instance of bean '" + beanName + "'");
		}
		RootBeanDefinition mbdToUse = mbd;

		// Make sure bean class is actually resolved at this point, and
		// clone the bean definition in case of a dynamically resolved Class
		// which cannot be stored in the shared merged bean definition.
		Class resolvedClass = resolveBeanClass(mbd, beanName);
		if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
			mbdToUse = new RootBeanDefinition(mbd);
			mbdToUse.setBeanClass(resolvedClass);
		}

		// Prepare method overrides.
		try {
			mbdToUse.prepareMethodOverrides();
		}
		catch (BeanDefinitionValidationException ex) {
			throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
					beanName, "Validation of method overrides failed", ex);
		}

		try {
			// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
                        // bean实例化前的处理,这部有可能可以直接生成代理。
			Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
			if (bean != null) {
				return bean;
			}
		}
		catch (Throwable ex) {
			throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
					"BeanPostProcessor before instantiation of bean failed", ex);
		}
                //我们重点看下这一步
		Object beanInstance = doCreateBean(beanName, mbdToUse, args);
		if (logger.isDebugEnabled()) {
			logger.debug("Finished creating instance of bean '" + beanName + "'");
		}
		return beanInstance;
	}
复制代码

  简单说下,这里列出方法的原因,是为了提一下,resolveBeforeInstantiation()-->applyBeanPostProcessorsBeforeInstantiation-->进入AbstractAutoProxyCreator.postProcessBeforeInstantiation(),我们看下其中的一个判断条件方法,


protected boolean isInfrastructureClass(Class beanClass) {
		boolean retVal = Advice.class.isAssignableFrom(beanClass) ||
				Pointcut.class.isAssignableFrom(beanClass) ||
				Advisor.class.isAssignableFrom(beanClass) ||
				AopInfrastructureBean.class.isAssignableFrom(beanClass);
		if (retVal && logger.isTraceEnabled()) {
			logger.trace("Did not attempt to auto-proxy infrastructure class [" + beanClass.getName() + "]");
		}
		return retVal;
	}
复制代码

  这个方法的意思是,用于代理增强的系统基础类,不需要代理,这个时候,满足条件的基础类会被标志为false。下文会用到。   我们继续流程链路doCreateBean()-->initializeBean()-->applyBeanPostProcessorsAfterInitialization()。


protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {
		if (System.getSecurityManager() != null) {
		    //markdown格式问题,把范型尖括号改了
			AccessController.doPrivileged(new PrivilegedAction「Object」() {
				@Override
				public Object run() {
					invokeAwareMethods(beanName, bean);
					return null;
				}
			}, getAccessControlContext());
		}
		else {
			invokeAwareMethods(beanName, bean);
		}

		Object wrappedBean = bean;
		if (mbd == null || !mbd.isSynthetic()) {
                        //执行bean处理器的postProcessBeforeInitialization()方法
			wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
		}

		try {
                        //执行初始化方法
			invokeInitMethods(beanName, wrappedBean, mbd);
		}
		catch (Throwable ex) {
			throw new BeanCreationException(
					(mbd != null ? mbd.getResourceDescription() : null),
					beanName, "Invocation of init method failed", ex);
		}
		if (mbd == null || !mbd.isSynthetic()) {
                        //执行bean处理器的postProcessAfterInitialization(),这一步是重点,我们继续往下走
			wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
		}
		return wrappedBean;
	}
复制代码

  此处可以看到,我们自动创建代理的DefaultAdvisorAutoProxyCreator已经注册,我们主要关注这个处理器的方法。我们进入AbstractAutoProxyCreator


@Override
	public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
		if (bean != null) {
			Object cacheKey = getCacheKey(bean.getClass(), beanName);
			if (!this.earlyProxyReferences.contains(cacheKey)) {
                                //关注这一步,进入方法
				return wrapIfNecessary(bean, beanName, cacheKey);
			}
		}
		return bean;
	}
复制代码

  顾名思义,如果有需要,就包装起来,就是处理增强用的


protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
		if (beanName != null && this.targetSourcedBeans.contains(beanName)) {
			return bean;
		}
		if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
			return bean;
		}
		if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
			this.advisedBeans.put(cacheKey, Boolean.FALSE);
			return bean;
		}

		// 获取增强和切面
		Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
		//markdown格式问题,把DONOTPROXY修改成null
		if (specificInterceptors != null) {
			this.advisedBeans.put(cacheKey, Boolean.TRUE);、
                        //我们把目光集中到这里
			Object proxy = createProxy(
					bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
			this.proxyTypes.put(cacheKey, proxy.getClass());
			return proxy;
		}

		this.advisedBeans.put(cacheKey, Boolean.FALSE);
		return bean;
	}
复制代码

protected Object createProxy(
			Class beanClass, String beanName, Object[] specificInterceptors, TargetSource targetSource) {

		if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
			AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);
		}

		ProxyFactory proxyFactory = new ProxyFactory();
		proxyFactory.copyFrom(this);

		if (!proxyFactory.isProxyTargetClass()) {
			if (shouldProxyTargetClass(beanClass, beanName)) {
				proxyFactory.setProxyTargetClass(true);
			}
			else {
				evaluateProxyInterfaces(beanClass, proxyFactory);
			}
		}

		Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
		proxyFactory.addAdvisors(advisors);
		proxyFactory.setTargetSource(targetSource);
		customizeProxyFactory(proxyFactory);

		proxyFactory.setFrozen(this.freezeProxy);
		if (advisorsPreFiltered()) {
			proxyFactory.setPreFiltered(true);
		}

		return proxyFactory.getProxy(getProxyClassLoader());
	}
复制代码

  看到这里,大家终于看到了和AOP相关的操作了,没错,他就是由ProxyFactory来处理的。下面,我们简单讲下ProxyFactory,之后,我们再继续jdk动态代理的流程

三、穿插讲下 ProxyFactory

  从上文方法中,我们可以看到,createProxy()方法中,大致的步骤就是创建一个ProxyFactory实例,然后设置各种属性之后,最后调用proxyFactory.getProxy(getProxyClassLoader())生成代理类。

public Object getProxy(ClassLoader classLoader) {
		return createAopProxy().getProxy(classLoader);
	}
复制代码
  首先我们看下createAopProxy()

protected final synchronized AopProxy createAopProxy() {
		if (!this.active) {
			activate();
		}
                //getAopProxyFactory()返回new DefaultAopProxyFactory()
                // 我们在具体看下createAopProxy方法
		return getAopProxyFactory().createAopProxy(this);
	}
复制代码
  从下面的方法中,我们可以看出,根据不同的条件,底层要么使用jdk动态代理,要么使用cglib动态代理

@Override
	public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
	      //优化,这个我没用过,书中介绍使用cglib代理 ||  true的时候用cglib  ||  目标类只有SpringProxy接口	
              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);
		}
	}
复制代码
  这里我们就只是简单讲下ProxyFactory(),便于大家理解就行。下面我们分两个小节讲下两个分支,即JdkDynamicAopProxy和ObjenesisCglibAopProxy。首先,我们回到jdk的动态代理话题。


  我们来看下JdkDynamicAopProxy如何创建代理


@Override
	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, true);
		findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
                //这一步直接调用jdk反射包创建代理,着重看下第三个参数,this,因为JdkDynamicAopProxy
                //实现了InvocationHandler接口,所以当生成的代理类对外服务的时候,会调用本类实现的invoke()方法
		return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
	}
复制代码

  从图中我们可以看到,这时候从容器中获取的bean,已经是经过代理生成的类了。执行waiter.greetTo("tom")的时候,会回调JdkDynamicAopProxy的invoke()方法。


@Override
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		MethodInvocation invocation;
		Object oldProxy = null;
		boolean setProxyContext = false;
                //获取目标类
		TargetSource targetSource = this.advised.targetSource;
		Class targetClass = null;
		Object target = null;

		try {
                        //代理的接口没有实现equals方法,并且方法名是equals
			if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
				// 代理实现equals方法.
				return equals(args[0]);
			}
			else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
				// 代理实现hashCode() .
				return hashCode();
			}
			else if (method.getDeclaringClass() == DecoratingProxy.class) {
				// There is only getDecoratedClass() declared -> dispatch to proxy config.
				return AopProxyUtils.ultimateTargetClass(this.advised);
			}
			else if (!this.advised.opaque && method.getDeclaringClass().isInterface() &&
					method.getDeclaringClass().isAssignableFrom(Advised.class)) {
				// Service invocations on ProxyConfig with the proxy config...
				return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
			}

			Object retVal;
                        //  如果exposeProxy==true
			if (this.advised.exposeProxy) {
				// 把这个代理放入ThreadLocal中,使其在线程中可见
				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 = targetSource.getTarget();
			if (target != null) {
				targetClass = target.getClass();
			}

			// 获取增强的拦截器链
			//markdown格式问题,把范型尖括号修改了
			List「Object」 chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);

			// 如果没有advice,那么不需要增强,直接反射调用方法
			if (chain.isEmpty()) {
				// 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 = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
			}
			else {
				// 创建一个ReflectiveMethodInvocation
				invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
				// 通过拦截器链执行连接点的增强方法。我们分析下proceed()
				retVal = invocation.proceed();
			}

			// Massage return value if necessary.
			Class returnType = method.getReturnType();
			if (retVal != null && retVal == target &&
					returnType != Object.class && returnType.isInstance(proxy) &&
					!RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {
				// Special case: it returned "this" and the return type of the method
				// is type-compatible. Note that we can't help if the target sets
				// a reference to itself in another returned object.
				retVal = proxy;
			}
			else if (retVal == null && returnType != Void.TYPE && returnType.isPrimitive()) {
				throw new AopInvocationException(
						"Null return value from advice does not match primitive return type for: " + method);
			}
			return retVal;
		}
		finally {
			if (target != null && !targetSource.isStatic()) {
				// Must have come from TargetSource.
				targetSource.releaseTarget(target);
			}
			if (setProxyContext) {
				// Restore old proxy.
				AopContext.setCurrentProxy(oldProxy);
			}
		}
	}
复制代码

@Override
	public Object proceed() throws Throwable {
		//	We start with an index of -1 and increment early.
                // interceptorsAndDynamicMethodMatchers为增强拦截器的数量,这个条件可以确保所有的拦截器执行完之后,再通过
                // 反射执行invokeJoinpoint(),即类本身的方法,比如本文中的waiter的greetTo("tom")方法
		if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
			return invokeJoinpoint();
		}
                // 依次执行增强拦截器(我尝试过修改配置顺序,发现链表的顺序和配置顺序一致,不过这里不影响结果)
		Object interceptorOrInterceptionAdvice =
				this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
		// InterceptorAndDynamicMethodMatcher类型的走这个流程,我们不管
                if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
			// Evaluate dynamic method matcher here: static part will already have
			// been evaluated and found to match.
			InterceptorAndDynamicMethodMatcher dm =
					(InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
			if (dm.methodMatcher.matches(this.method, this.targetClass, this.arguments)) {
				return dm.interceptor.invoke(this);
			}
			else {
				// Dynamic matching failed.
				// Skip this interceptor and invoke the next in the chain.
				return proceed();
			}
		}
		else {
			// 我们依次去调用拦截器链的方法,由于本文案例注册了两个拦截器,下文依次给出
                        // 注意invoke方法中的参数是this,用于从拦截器方法中回来
			return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
		}
	}
复制代码

  首先我们看下前置增强的拦截器方法


public class MethodBeforeAdviceInterceptor implements MethodInterceptor, Serializable {

	private MethodBeforeAdvice advice;


	/**
	 * Create a new MethodBeforeAdviceInterceptor for the given advice.
	 * @param advice the MethodBeforeAdvice to wrap
	 */
	public MethodBeforeAdviceInterceptor(MethodBeforeAdvice advice) {
		Assert.notNull(advice, "Advice must not be null");
		this.advice = advice;
	}

	@Override
	public Object invoke(MethodInvocation mi) throws Throwable {
                //首先执行前置增强方法,这里会跳到我们的前置增强实现类GreetBeforeAdvice,执行before()方法
                // 输出 “greetTo方法执行前,do something”
		this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis() );
                // 然后回到ReflectiveMethodInvocation的proceed方法,继续执行剩下的增强拦截器,看下文
		return mi.proceed();
	}

}
复制代码

  执行后置增强的拦截器方法


public class AfterReturningAdviceInterceptor implements MethodInterceptor, AfterAdvice, Serializable {
	private final AfterReturningAdvice advice;
	/**
	 * Create a new AfterReturningAdviceInterceptor for the given advice.
	 * @param advice the AfterReturningAdvice to wrap
	 */
	public AfterReturningAdviceInterceptor(AfterReturningAdvice advice) {
		Assert.notNull(advice, "Advice must not be null");
		this.advice = advice;
	}

	@Override
	public Object invoke(MethodInvocation mi) throws Throwable {
                //先执行类本身的方法,即proceed()-->invokeJoinpoint(),通过反射调用目标类KfcWaiter的greetTo(String name)方 
                //法(tips:这里要多说一句,便于大家理解,因为本文就两个增强拦截器,并且后置增强是最后一个,所以这里会直接执行目标类)
                //的方法,如果后置增强拦截器不是最后一个执行,那么该方法会回到ReflectiveMethodInvocation.proceed()继续调用拦截 
                //器方法。上文中我也提到过,拦截器链虽然按配置顺序排列,但是不影响流程最终的执行顺序)
		Object retVal = mi.proceed();
                //执行后置增强拦截器的方法,这里会调用我们实现的GreetAfterAdvice,执行afterReturning方法
		this.advice.afterReturning(retVal, mi.getMethod(), mi.getArguments(), mi.getThis());
                //这里特别说下,后置增强是在目标类方法执行完毕之后执行,但是目标类的执行结果是在后置方法执行完毕后再返回的
		return retVal;
	}
}
复制代码

  好了,到这里,jdk动态代理的流程就讲完了,下面我们一起看下cglib动态代理的流程。这块cglib的底层实现我没有去看过,这里只能带大家看下AOP的流程了,讲的不是那么详细,但是对于理解流程应该是没问题了。

四、cglib动态代理

![ObjenesisCglibAopProxy继承图][image5]   首先我们把xml配置文件中的proxyTargetClass属性设置为true,告诉spring我们要使用cglib来生成代理。   下面我们看下ObjenesisCglibAopProxy的getProxy()方法,由父类CglibAopProxy实现。从下面代码中可以看出,ObjenesisCglibAopProxy主要是创建cglib中的Enhancer,设置相应的属性,然后利用Enhancer生成代理

@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;
                    //如果rootClass是cglib代理生成的子类
		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);

		// 创建并配置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));
                    //这里,我们要讲下这个getCallbacks()方法,它确认了增强和这些增强的拦截器作为回调
		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 (Throwable ex) {
		// TargetSource.getTarget() failed
		throw new AopConfigException("Unexpected AOP exception", ex);
	}
}
复制代码
复制代码

复制代码

  获取回调


private Callback[] getCallbacks(Class rootClass) throws Exception {
		// 一些优化参数,这里可以忽略
		boolean exposeProxy = this.advised.isExposeProxy();
		boolean isFrozen = this.advised.isFrozen();
		boolean isStatic = this.advised.getTargetSource().isStatic();

		// 选择DynamicAdvisedInterceptor作为aop拦截器,执行回调方法
		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 optimizations 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];
			//markdown格式问题,把尖括号修改了
			this.fixedInterceptorMap = new HashMap「String, Integer」(methods.length);

			// TODO: small memory optimization here (can skip creation for methods with no advice)
			for (int x = 0; x < methods.length; x++) {
			//markdown格式问题,把尖括号修改了
				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;
	}
复制代码

![回到启动类]tips:由于base64文件太大了,文章保存不下,这张图片就不显示了

  我们看到从容器中获取的waiter实例已经是经过cglib代理后生成的类。执行waiter.greetTo("tom")方法,会执行上文中注册的DynamicAdvisedInterceptor拦截器的方法intercept()。大家有没有发现逻辑简直跟上面讲解jdk的动态代理回调时候一模一样。


@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();
				}
                                //获取拦截器链
                                //markdown格式问题,把尖括号修改了
				List「Object」 chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
				Object retVal;
				// 无拦截器,直接通过反射调用方法
				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 {
					// 创建并执行MethodInvocation的proceed()方法。CglibMethodInvocation是
                                        // ReflectiveMethodInvocation的子类,执行步骤和上文讲jdk代理的流程一样了,就
                                        // 不重复唠叨了
					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);
				}
			}
		}
复制代码

五、小结

  由于我刚开始用markdown,对本文代码中冲突的尖括号都特殊处理了,并由标注指出,敬请见谅。

  本文主要是和大家一起了解下AOP的源码实现流程,对于cglib等底层实现没有涉猎。后续我如果有需求要啃cglib的源码,那么对应的文章也会分享给大家。有什么讲解错误的,希望大家在评论区不吝指正。?

转载于:https://juejin.im/post/5bd7d53af265da0ab9161351

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值