SpringAOP终结篇(补充中...)

Posted 一点学习的记录

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SpringAOP终结篇(补充中...)相关的知识,希望对你有一定的参考价值。

一、基本源码分析

1.寻找入口

Spring 的 AOP 是通过接入 BeanPostProcessor 后置处理器开始的

2.BeanPostProcessor

BeanPostProcessor的体现在IOC源码分析的doCreateBean中,populateBean的后一句

Object exposedObject = bean;
try {
   populateBean(beanName, mbd, instanceWrapper);
   exposedObject = initializeBean(beanName, exposedObject, mbd);
}

initializeBean中,在调用invokeInitMethods初始化方法的前后调用BeanPostProcessor

Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
   wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}

try {
   invokeInitMethods(beanName, wrappedBean, mbd);
}
catch (Throwable ex) {
   //...
}
if (mbd == null || !mbd.isSynthetic()) {
   wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}

其实就是在你的init方法前后调用BeanPostProcessor的before方法和after方法。

在 Spring 中,BeanPostProcessor 的实现子类非常的多,分别完成不同的操作,如:AOP 面向切面编程的注册通知适配器、Bean 对象的数据校验、Bean 继承属性、方法的合并等等。

分析创建AOP代理对象的相关BeanPostProcessor子类AbstractAutoProxyCreator(经典实现类AnnotationAwareAspectJAutoProxyCreator) 。

3.AbstractAutoProxyCreator

AbstractAutoProxyCreator的postProcessAfterInitialization ,即after方法

public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
   if (bean != null) {
      Object cacheKey = getCacheKey(bean.getClass(), beanName);
      if (!this.earlyProxyReferences.contains(cacheKey)) {
         return wrapIfNecessary(bean, beanName, cacheKey);
      }
   }
   return bean;
}

核心逻辑在wrapIfNecessary,里面主要几步

1.判断是不是该wrap包装(AOP代理):是不是缓存过、基础Bean(Advice/PointCut/Advisor)跳过

2.获取这个Bean的advice

3.处理advice去createProxy创建代理对象并缓存

核心当然是createProxy,最终是交给了工厂proxyFactory.getProxy(),最终到DefaultAopProxyFactory的 createAopProxy()方法

4.DefaultAopProxyFactory#createAopProxy()

public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
   if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
      Class<?> targetClass = config.getTargetClass();
      if (targetClass == null) {
         //...
      }
      if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
         return new JdkDynamicAopProxy(config);
      }
      return new ObjenesisCglibAopProxy(config);
   }
   else {
      return new JdkDynamicAopProxy(config);
   }
}

两种方式来生成代理方式有 JDKProxy 和 CGLib

来分析一下spring中JDK动态代理如何运作的,织入切面的,对应是JdkDynamicAopProxy

5.JdkDynamicAopProxy

InvocationHandler 是 JDK 动态代理的核心,生成的代理对象的方法调用都会委托到InvocationHandler.invoke()方法。JdkDynamicAopProxy 的源码可以看到这个类也实现了 InvocationHandler,

5.1 invoke()方法:

避免一些不aop的特殊情况后,首先获取应用到此方法上的通知链(Interceptor Chain)。如果有通知,则应用通知,并执行 JoinPoint;如果没有通知,则直接反射执行 JoinPoint。

5.2 获取通知链

getInterceptorsAndDynamicInterceptionAdvice 方法:

1从提供的配置实例 config 中获取 advisor 列表,

2 遍历处理这些 advisor.如果是 IntroductionAdvisor,则判断此 Advisor 能否应用到目标类 targetClass 上.

3.如果是 PointcutAdvisor,则判断此 Advisor 能否应用到目标方法 Method 上.

4.将满足条件的 Advisor 通过 AdvisorAdaptor 转化成 Interceptor 列表返回.

这个方法执行完成后,Advised 中配置能够应用到连接点(JoinPoint)或者目标类(Target Object)
的 Advisor 全部被转化成了 MethodInterceptor

5.3 执行

获取完通知链之后就是执行了:

List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
if (chain.isEmpty()) {
   Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
   retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
}
else {
   invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
   retVal = invocation.proceed();
}

核心就是retVal = invocation.proceed();打开ReflectiveMethodInvocation的proceed源码:

public Object proceed() throws Throwable {
	//1.如果 Interceptor 执行完了, 则执行 joinPoint
	if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
		return invokeJoinpoint();
	}
	Object interceptorOrInterceptionAdvice =this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
	//2.如果要动态匹配 joinPoint
	InterceptorAndDynamicMethodMatcher dm =(InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
	//3.动态匹配: 运行时参数是否满足匹配条件
	if (dm.MethodMatcher.matches(this.Method, this.targetClass, this.arguments)) {
		return dm.interceptor.invoke(this);
	} else {
		//动态匹配失败时,略过当前 Intercetpor,调用下一个 Interceptor
		return proceed();
	}
} else {
	//4.执行当前 Intercetpor
	return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
}
}

1.从执行链里取Interceptor(排序好了,依次是before、after、return、afterthrowing)

2.分两种情况,Interceptor是否是动态匹配型的

? 2.1 动态匹配型,去执行动态匹配代码,匹配上则执行

? 2.2 普通型else,直接执行Interceptor逻辑(这个逻辑里排好代码,是先继续递归还是先执行自己,before是先执行自己)如下:

beofore-Interceptor的的invoke(先自己再继续递归)

public Object invoke(MethodInvocation mi) throws Throwable {
   this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis());
   return mi.proceed();
}

after-Interceptor的的invoke(先继续递归,再执行自己)

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

以上是关于SpringAOP终结篇(补充中...)的主要内容,如果未能解决你的问题,请参考以下文章

SpringAOP的简单使用

SpringAOP 面试题

跟我一起学docker(18)--持续集成(初级终结篇)

SpringAOP第一个案例

浏览器渲染 理解终结篇

AOP——SpringAOP