Spring之AOP源码

大致流程主要分为三个步骤:
1: 创建AnnotationAwareAspectJAutoProxyCreator对象
2: 扫描容器中的切面,创建PointcutAdvisor对象
3: 生成代理类

创建AnnotationAwareAspectJAutoProxyCreator对象

在配置类上面添加@EnableAspectJAutoProxy注解开启AOP,EnableAspectJAutoProxy类:

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(AspectJAutoProxyRegistrar.class)
public @interface EnableAspectJAutoProxy {

	/**
	 * Indicate whether subclass-based (CGLIB) proxies are to be created as opposed
	 * to standard Java interface-based proxies. The default is {@code false}.
	 */
	boolean proxyTargetClass() default false;

	/**
	 * Indicate that the proxy should be exposed by the AOP framework as a {@code ThreadLocal}
	 * for retrieval via the {@link org.springframework.aop.framework.AopContext} class.
	 * Off by default, i.e. no guarantees that {@code AopContext} access will work.
	 * @since 4.3.1
	 */
	boolean exposeProxy() default false;

}

EnableAspectJ?让我们的java程序支持AspectJ?其实是开启对AspectJ语法风格的支持

@Import(AspectJAutoProxyRegistrar.class):给容器导入AspectJAutoProxyRegistrar

class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar {

	/**
	 * Register, escalate, and configure the AspectJ auto proxy creator based on the value
	 * of the @{@link EnableAspectJAutoProxy#proxyTargetClass()} attribute on the importing
	 * {@code @Configuration} class.
	 */
	@Override
	public void registerBeanDefinitions(
			AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {

		AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);

		AnnotationAttributes enableAspectJAutoProxy =
				AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class);
		if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) {
			AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
		}
		if (enableAspectJAutoProxy.getBoolean("exposeProxy")) {
			AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
		}
	}

}

利用AspectJAutoProxyRegistrar来给容器注册注册了一个切面相关BeanDefinition,正是上面提到的类:AnnotationAwareAspectJAutoProxyCreator

AnnotationAwareAspectJAutoProxyCreator

该类的父类实现了SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware两个接口。结合IOC的流程来看,先是会注册BeanPostProcessor,保存在容器中,然后在bean的生命周期过程IOC 最后一个扩展方法postProcessAfterInitialization中创建代理对象

SmartInstantiationAwareBeanPostProcessor

postProcessBeforeInstantiation方法

SmartInstantiationAwareBeanPostProcessor会在创建Bean实例之前先尝试用postProcessBeforeInstantiation方法,做一些准备工作,比如判断当前Bean是否需要被代理,将通知方法封装成为增强器集合List<Advisor> candidateAdvisors等

postProcessAfterInitialization方法

真正发挥作用的是BeanPostProcessor.postProcessAfterInitialization方法,AnnotationAwareAspectJAutoProxyCreator的父类AbstractAdvisorAutoProxyCreator重写了BeanPostProcessor.postProcessAfterInitialization方法,所以实际执行的是:

	@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;
	}

那么主要看下wrapIfNecessary方法的逻辑:

	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);
		if (specificInterceptors != DO_NOT_PROXY) {
			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;
	}

 creatProxy方法

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);
		for (Advisor advisor : advisors) {
			proxyFactory.addAdvisor(advisor);
		}

		proxyFactory.setTargetSource(targetSource);
		customizeProxyFactory(proxyFactory);

		proxyFactory.setFrozen(this.freezeProxy);
		if (advisorsPreFiltered()) {
			proxyFactory.setPreFiltered(true);
		}
                //自动判断用cglib动态代理或者是jdk动态代理生成代理对象
		return proxyFactory.getProxy(getProxyClassLoader());
	}

给容器返回增强了之后的代理对象,以后从容器中获取到的就是这个对象的代理对象,执行目标方法的时候,代理对象会去执行通知方法

拦截器链的执行流程

容器中保存了组件的代理对象,这个对象里面保存了详细信息(比如增强器,目标对象)如果没有拦截器链,直接执行目标方法,下面我们主要介绍有拦截器链的情况。

现在假设代理对象proxy调用了某个方法,那么这个方法会触发CglibAopProxy.intercept()方法,intercept()方法说穿了,就做了两件事:

①收集拦截器,做成链

②将需要执行的目标对象,目标方法,拦截器链等信息传入创建一个MethodInvocation对象,这对象可以理解为一个大杂烩。所有AOP功能所需要的的材料都在这里了,包括目标对象,拦截器链等,并调用MethodInvocation.proceed()方法,也就是拦截器链的触发过程,proceed方法就做了两件事:

①先执行全部的拦截器

②最后执行目标方法

	public Object proceed() throws Throwable {
		//如果拦截器链执行完毕了,那么直接调用目标方法
		if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
			return invokeJoinpoint();
		}
                //currentInterceptorIndex+1,执行拦截器的invoke方法
		Object interceptorOrInterceptionAdvice =
				this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
		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 {
			// 
			return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
		}
	}

看到这里,可能会有疑问:既然拦截器都在目标方法之前执行,怎么实现AOP这种汉堡似的包夹调用顺序呢?我们来看看拦截器的invoke方法干了啥:

刚才说过了,拦截器是对增强器的包装,而我们的增强方法,Before/AfterReturning等等,所以拦截器肯定也有对应的Before/AfterReturning,我们先看看Before拦截器

@SuppressWarnings("serial")
public class MethodBeforeAdviceInterceptor implements MethodInterceptor, BeforeAdvice, Serializable {

	private final 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 {
		this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis());
		return mi.proceed();
	}

}

我们发现:

  • 先调用了this.advice.before(),即反射执行@Before方法
  • 再调用了MethodInvocation.proceed()方法

再来看看After拦截器

@SuppressWarnings("serial")
public class AspectJAfterAdvice extends AbstractAspectJAdvice
		implements MethodInterceptor, AfterAdvice, Serializable {

	public AspectJAfterAdvice(
			Method aspectJBeforeAdviceMethod, AspectJExpressionPointcut pointcut, AspectInstanceFactory aif) {

		super(aspectJBeforeAdviceMethod, pointcut, aif);
	}


	@Override
	public Object invoke(MethodInvocation mi) throws Throwable {
		try {
			return mi.proceed();
		}
		finally {
			invokeAdviceMethod(getJoinPointMatch(), null, null);
		}
	}

	@Override
	public boolean isBeforeAdvice() {
		return false;
	}

	@Override
	public boolean isAfterAdvice() {
		return true;
	}

}
  • 先调用了MethodInvocation.proceed()方法
  • 后反射调用了@After方法

Before和After拦截器有什么不一样?

Before拦截器是先反射调用@Before,再调用proceed方法

After拦截器是先调用proceed,再反射调用@AfterReturning方法

其实只有Before是特殊的,其他拦截器都是先调用proceed方法,再反射调用通知方法。

链式获取每个拦截器,拦截器执行invoke方法,每个拦截器等待下一个拦截器执行完了之后返回,拦截器链的机制,保证通知方法和目标方法的执行顺序。

总结

  1. @EnableAspectJAutoProxy开启AOP功能
  2. EnableAspectJAutoProxy会给容器注册一个AnnotationAwareAspectJAutoProxyCreator组件
  3. AnnotationAwareAspectJAutoProxyCreator是一个BeanPostProcessor
  4. 在IOC的流程中,当创建单例对象的时候,BeanPostProcessor的BeanPostProcessor的postProcessAfterInitialization方法会对此过程进行拦截,也就是说单例对象创建完成之后,判断该对象是否需要增强
  5. 如果判断需要被增强,那么将该对象的通知方法封装成为增强器,一个个的增强器再封装成为一个个的拦截器,形成一个拦截器链
  6. 将目标方法,拦截器链等信息传入创建一个MethodInvocation对象,调用MethodInvocation.proceed方法
  7. 利用拦截器的链式机制,最终的效果

        正常执行:前置通知-》目标方法-》后置通知-》返回通知

        异常执行:前置通知-》目标方法-》后置通知-》异常通知

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

猎户星座。

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值