Spring AOP 注解配置解析原理一

1.1 AOP的使用

1. 创建拦截的Bean

 @Configuration
 @Import(value=LogAspect.class)
 @EnableAspectJAutoProxy
 public class MathCalculator {
 	public int div(int i,int j){
 		System.out.println("MathCalculator...div...");
 		return i/j;	
 	}
 
 	@SuppressWarnings("resource")
 	public static void main(String[] args) {
 		AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(MathCalculator.class);
 		MathCalculator mathCalculator = ac.getBean(MathCalculator.class);
 		mathCalculator.div(1, 2);
 	}
}

2. 创建Advisor

@Aspect
public class LogAspect {
	
	//抽取公共的切入点表达式
	//1、本类引用
	//2、其他的切面引用
	@Pointcut("execution(* com.gz.MathCalculator.*(..))")
	public void pointCut(){};
	
	//@Before在目标方法之前切入;切入点表达式(指定在哪个方法切入)
	@Before("pointCut()")
	public void logStart(JoinPoint joinPoint){
		Object[] args = joinPoint.getArgs();
		System.out.println(""+joinPoint.getSignature().getName()+"运行。。。@Before:参数列表是:{"+Arrays.asList(args)+"}");
	}
	
	@After("com.gz.LogAspect.pointCut()")
	public void logEnd(JoinPoint joinPoint){
		System.out.println(""+joinPoint.getSignature().getName()+"结束。。。@After");
	}
	
	//JoinPoint一定要出现在参数表的第一位
	@AfterReturning(value="pointCut()",returning="result")
	public void logReturn(JoinPoint joinPoint,Object result){
		System.out.println(""+joinPoint.getSignature().getName()+"正常返回。。。@AfterReturning:运行结果:{"+result+"}");
	}
	
	@AfterThrowing(value="pointCut()",throwing="exception")
	public void logException(JoinPoint joinPoint,Exception exception){
		System.out.println(""+joinPoint.getSignature().getName()+"异常。。。异常信息:{"+exception+"}");
	}

}


1.2 AOP处理流程

跟踪@EnableAspectJAutoProxy注解

《Spring AOP 注解配置解析原理一》
《Spring AOP 注解配置解析原理一》
《Spring AOP 注解配置解析原理一》

根据@EnableAspectJAutoProxy注解可知,该注解@Import(AspectJAutoProxyRegistrar.class)给容器中导入AspectJAutoProxyRegistrar。利用AspectJAutoProxyRegistrar自定义给容器中注册bean;
跟踪代码,最终注入AnnotationAwareAspectJAutoProxyCreator类。

AnnotationAwareAspectJAutoProxyCreator类图
《Spring AOP 注解配置解析原理一》

从上边的类图关系我们发现两个重要的接口BeanFactoryAware和SmartInstantiationAwareBeanPostProcessor接口。

在AbstractAdvisorAutoProxyCreator类中setBeanFactory(BeanFactory beanFactory)方法上打上断点跟踪代码,如下:。

我们先了解Spring实例化对象具体步骤如下:

  1. 传入配置类、创建IOC容器

  2. 注册配置类,调用refresh()刷新容器

  3. registerBeanPostProcesors(beanFactory)注册bean的后置处理器来拦截bean的创建

    3.1. 先获取IOC容器已经定义的需要创建对象的所有BeanPostProcessor

    3.2. 给容器中加别的BeanPostProcessor

    3.3. 优先注册了PriorityOrdered接口的BeanPostProcessor

    3.4. 再给容器中注册了Ordered接口的BeanPostProcessor

    3.5. 注册没有实现优先级接口的BeanPostProcessor

    3.6. 注册BeanPostProcessor,实际上就是创建BeanPostProcessor对象,保存到容器中创建internalAutoProxyCreator的BeanPostProcessor【AnnotationAwareAspectJAutoProxyCreator】
    3.6.1. 创建Bean的实例
    3.6.2. populateBean,给Bean各种属性赋值
    3.6.3. initializeBean,初始化Bean
    3.6.3.1. invokeAwareMethods(),处理Aware接口的方法回调
    3.6.3.2. applyBeanPostProcessorsBeforeInitialization(),执行后置处理器的postProcessBeforeInitialization()方法
    3.6.3.3. invokeInitMethods(),执行初始化方法
    3.6.3.4. applyBeanPostProcessorsAfterInitialization(),执行后置处理器的postProcessAfterInitialization()方法

  4. finishBeanFactoryInitialization(),完成BeanFactory初始化工作,完成剩下的单例Bean

    4.1. 遍历获取容器中所有的Bean,依次创建对象getBean(beanName); getBean()->doGetBean()-> getSingleton()

    4.2. 创建Bean
    4.2.1. 先从缓存中获取Bean,如果能获取,说明之前创建过,直接返回,否则创建。
    4.2.2. createBean ();创建Bean
    4.2.2.1. resolveBeforeInstantiation(beanName,mbdToUse);解析BeforeInstantia
    希望后置处理器在此能返回一个代理对象,如果能返回代理对象就使用,否则继续
    4.2.2.1.1. 如果是InstantiationAwareBeanPostProcessor后置处理器
    后置处理器尝试创建代理Bean
    4.2.2.2. doCreateBean(beanName, mbdToUse, args)和3.6的步骤一样

关于Spring后置处理器:

  1. BeanPostProcessor:是在Bean对象创建完成出事前后调用的
  2. InstantiationAwareBeanPostProcessor:是在创建Bean实例之前先尝试用后置处理器返回

根据类的继承关系我们知道AnnotationAwareAspectJAutoProxyCreator继承自InstantiationAwareBeanPostProcessor,根据以上流程4.2我们知道在每一个Bean创建之前,调用postProcessBeaforeInstantiation()。

在AbstractAutoProxyCreator类中postProcessBeforeInstantiation(Class<?> beanClass, String beanName)方法上打上断点跟踪代码,如下:
初始化前(postProcessBeforeInstantiation)

public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
		Object cacheKey = getCacheKey(beanClass, beanName);

		if (beanName == null || !this.targetSourcedBeans.contains(beanName)) {
		   // 判断当前Bean是否在advisedBeans中,(保存了所有需要增强的Bean)
			if (this.advisedBeans.containsKey(cacheKey)) {
				return null;
			}
			// 判断当前Bean是否是基础类型||是否需要跳过
			if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {
				this.advisedBeans.put(cacheKey, Boolean.FALSE);
				return null;
			}
		}

		// Create proxy here if we have a custom TargetSource.
		// Suppresses unnecessary default instantiation of the target bean:
		// The TargetSource will handle target instances in a custom fashion.
		if (beanName != null) {
			TargetSource targetSource = getCustomTargetSource(beanClass, beanName);
			if (targetSource != null) {
				this.targetSourcedBeans.add(beanName);
				Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);
				Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);
				this.proxyTypes.put(cacheKey, proxy.getClass());
				return proxy;
			}
		}

		return null;
	}
  1. AbstractAutoProxyCreator.postProcessBeforeInstantiation()方法
    1.1. 判断当前Bean是否在advisedBeans中,(保存了所有需要增强的Bean)
    1.2. 判断当前Bean是否是基础类型,Advice、Pointcut、Advisor、AopInfrastructureBean或者是不是切面(@Aspect)
    1.3. 是否需要跳过
    1.3.1. 是否是候选的增强器(切面里面的通知方法),判断每一个增强器是否是AspectJPointcutAdvisor类型,是返回true,否则false【每一个封装的通知方法的增强器是InstantiationModelAwarePointcutAdvisor】

    1.3.2. 永远返回false

初始化后(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;
	}
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;
		}

		// Create proxy if we have advice.
		// 获取当前bean的所有增强器(如果采用的是BeanNameAutoProxyCreator类处理,此时不会获取Advisor,
		会在createProxy方法中获取,
		具体看createProxy方法中的buildAdvisors(beanName, specificInterceptors);)
		
		Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
		if (specificInterceptors != DO_NOT_PROXY) {
		// 保存当前bean在advisedBeans中
			this.advisedBeans.put(cacheKey, Boolean.TRUE);
			// 如果当前Bean需要增强器,创建当前Bean代理对象
			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;
	}
// 如果当前Bean需要增强器,创建当前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); // copy代理配置,如proxyTargetClass,exposeProxy等

		if (!proxyFactory.isProxyTargetClass()) {// false -> jdk代理;true -> cglib代理
		   // 再次确认是否要代理类对象
			if (shouldProxyTargetClass(beanClass, beanName)) {
				proxyFactory.setProxyTargetClass(true);
			}
			else {
			 // 不需要则获取其代理接口集合
				evaluateProxyInterfaces(beanClass, proxyFactory);
			}
		}

		Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
		proxyFactory.addAdvisors(advisors);// 增强器(通知方法)
		proxyFactory.setTargetSource(targetSource);// 目标类
		customizeProxyFactory(proxyFactory);// 是否冻结,及继续往里面加Advisor(通知方法)

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

		return proxyFactory.getProxy(getProxyClassLoader());
	}
  1. 创建对象,调用postProcessAfterInitialization()
    2.1. 获取当前bean的所有增强器(通知方法)
    2.1.1. 找到候选的所有的增强器
    2.1.2. 获取到能在bean中使用的增强器
    2.1.3. 对找到的增强器排序

    2.2. 保存当前bean在advisedBeans中

    2.3. 如果当前Bean需要增强器,创建当前Bean代理对象
    2.3.1. 获取所有增强器(通知方法)
    2.3.2. 保存到ProxyFactory
    2.3.3. 创建代理对象,Spring自动决定
    2.3.3.1. JdkDynamicAopProxy jdk动态代理
    2.3.3.2. ObjenesisCglibAopProxy cglib动态代理

  2. 目标方法执行
    容器中保存了组件的代理对象(cglib增强后的对象),这个对象里面保存了详细信息
    3.1. CglibAopProxy.intercept();拦截目标方法的执行

    3.2. 根据ProxyFactory获取执行将要执行的拦截器链
    3.2.1. List interceptorList保存所有的拦截器
    3.2.2. 遍历所有的增强器,将其转化为Interceptor;
    3.2.3. 将增强器转化List;如果是MethodInterceptor,直接放到结合中,
    如果不是,使用AdvisorAdapter转化为MethodInterceptor,

    3.3. 如果没有拦截器链,直接执行目标方法

    3.4. 如果有拦截器链,把需要执行的目标对象,目标方法,拦截器链等信息传入创建一个CglibMethodInvocation对象,返回结果

    原文作者:AOP
    原文地址: https://blog.csdn.net/u010811939/article/details/80802225
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞