浅尝Spring注解开发_AOP原理及完整过程分析(源码)

浅尝Spring注解开发_自定义注册组件、属性赋值、自动装配
浅尝Spring注解开发_Bean生命周期及执行过程
浅尝Spring注解开发_AOP原理及完整过程分析(源码)

AOP注解使用

1、导入aop模块;Spring AOP:(spring-aspects)
2、定义一个业务逻辑类(MathCalculator);在业务逻辑运行的时候将日志进行打印(方法之前、方法运行结束、方法出现异常,xxx)
3、定义一个日志切面类(LogAspects):切面类里面的方法需要动态感知MathCalculator.div运行到哪里然后执行;
  	通知方法:
  		前置通知(@Before):logStart:在目标方法(div())运行之前运行
  		后置通知(@After):logEnd:在目标方法(div())运行结束之后运行(无论方法正常结束还是异常结束)
  		返回通知(@AfterReturning):logReturn:在目标方法(div())正常返回之后运行
  		异常通知(@AfterThrowing):logException:在目标方法(div())出现异常以后运行
  		环绕通知(@Around):动态代理,手动推进目标方法运行(joinPoint.procced())
4、给切面类的目标方法标注何时何地运行(通知注解);
5、将切面类和业务逻辑类(目标方法所在类)都加入到容器中;
6、必须告诉Spring哪个类是切面类(给切面类上加一个注解:@Aspect)
[7]、给配置类中加 @EnableAspectJAutoProxy 【开启基于注解的aop模式】
  		在Spring中很多的 @EnableXXX;
  1. 导入aop模块:org.springframework.spring-aspects

    		<dependency>
    			<groupId>org.springframework</groupId>
    			<artifactId>spring-aspects</artifactId>
    			<version>4.3.12.RELEASE</version>
    		</dependency>
    
  2. 定义一个业务逻辑类(MathCalculator)。在业务逻辑运行的时候将日志进行打印(方法之前、方法运行结束、方法出现异常,xxx)。

    //业务类
    public class MathCalculator {
    
    	public int div(int i,int j){
    		System.out.println("MathCalculator...div...");
    		return i/j;
    	}
    
    }
    
  3. 定义一个日志切面类(LogAspects):切面类里面的方法需要动态感知MathCalculator.div运行到哪里然后执行。通知方法:

    1. 前置通知(@Before):logStart:在目标方法(div)运行之前运行
    2. 最终通知(@After):logEnd:在目标方法(div)运行结束之后运行(无论方法正常结束还是异常结束)
    3. 后置通知/返回通知(@AfterReturning):logReturn:在目标方法(div)正常返回之后运行
    4. 异常通知(@AfterThrowing):logException:在目标方法(div)出现异常以后运行
    5. 环绕通知(@Around):动态代理,手动推进目标方法运行(joinPoint.proceed())
  4. 给切面类的目标方法标注何时何地运行(通知注解)。

    //@Aspect: 告诉Spring当前类是一个切面类
    @Aspect
    public class LogAspects {
    
    	//抽取公共的切入点表达式,空方法,只使用注解
    	//1、本类引用使用:pointCut()
    	//2、其他的切面引用使用:com.xxx.aop.LogAspects.pointCut()
    	@Pointcut("execution(public int com.atguigu.aop.MathCalculator.*(..))")
    	public void pointCut(){};
    
    	//前置通知,JoinPoint可以获取切入点信息
    	//@Before在目标方法之前切入,切入点表达式(指定在哪个方法切入),JoinPoint封装了切面方法信息
    	@Before("pointCut()")
    	public void logStart(JoinPoint joinPoint){
    		Object[] args = joinPoint.getArgs();
    		System.out.println(""+joinPoint.getSignature().getName()+"运行...@Before:参数列表是:{"+Arrays.asList(args)+"}");
    	}
    
    	//最终通知
    	@After("com.atguigu.aop.LogAspects.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+"}");
    	}
    
    }
    
  5. 将切面类和业务逻辑类(目标方法所在类)都加入到容器中。

  6. 必须告诉Spring哪个类是切面类(给切面类上加一个注解:@Aspect)。

  7. 给配置类中加 @EnableAspectJAutoProxy (开启基于注解的aop模式)

    • 在Spring中很多的 @EnableXXX
    //开启基于注解的aop模式
    @EnableAspectJAutoProxy
    @Configuration
    public class MainConfigOfAOP {
    
    	//业务逻辑类加入容器中
    	@Bean
    	public MathCalculator calculator(){
    		return new MathCalculator();
    	}
    
    	//切面类加入到容器中
    	@Bean
    	public LogAspects logAspects(){
    		return new LogAspects();
    	}
    }
    
  8. 测试

    • 必须使用Spring容器调用

      public class IOCTest_AOP {
      
      	@Test
      	public void test01(){
      		AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfigOfAOP.class);
      
      		//1、不要自己创建对象
      //		MathCalculator mathCalculator = new MathCalculator();
      //		mathCalculator.div(1, 1);
      		MathCalculator mathCalculator = applicationContext.getBean(MathCalculator.class);
      
      		mathCalculator.div(1, 0);
      
      		applicationContext.close();
      	}
      
      }
      
    • 输出

      div运行...@Before:参数列表是{[1,0]}
      //业务方法运行
      MathCalculator...div...
      div结束...@After
      div异常...异常信息:{java.lang.ArithmeticException: / by zero}
      

⭐AOP原理

  1. 先将AnnotationAwareAspectJAutoProxyCreator(注释感知AspectJ自动代理创建器)注入容器
    0. AnnotationAwareAspectJAutoProxyCreator[BeanPostProcessor]本身也是Bean,Bean注入的过程如下:
    1. InstantiationAwareBeanPostProcessor实例化后置处理器
    2. 创建Bean实例
    3. InstantiationAwareBeanPostProcessor实例化后置处理器
    4. Bean属性赋值
    5. 初始化Bean
      0. 每一个[自定义等]初始化都要执行,过程如下:
      1. 处理Aware接口的方法回调
      2. BeanPostProcessor初始化后置处理器前置方法
      3. [自定义]初始化
      4. BeanPostProcessor初始化后置处理器后置方法

⭐开始时干了啥?@EnableAspectJAutoProxy注解

  1. 进入@EnableAspectJAutoProxy
  2. 发现注解@Import(AspectJAutoProxyRegistrar.class)给容器中导入AspectJAutoProxyRegistrar组件
  3. 它实现了ImportBeanDefinitionRegistart,这是一个接口,可以实现自定义注册组件(在之前的注入组件文章中讲过)
  4. 它给容器自定义注册bean定义信息(BeanDefinetion) ,就是org.springframework.aop.config.internalAutoProxyCreator,类型是AnnotationAwareAspectJAutoProxyCreator(注解装配模式的AspectJ切面自动代理创建器)
  5. 并且判断@EnableAspectJAutoProxy注解并处理信息

AnnotationAwareAspectJAutoProxyCreator继承关系

AnnotationAwareAspectJAutoProxyCreator
	-> extends AspectJAwareAdvisorAutoProxyCreator
		-> extends AbstractAdvisorAutoProxyCreator
			-> extends AbstractAutoProxyCreator
				implements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware(关注后置处理器(在bean初始化完成前后做事情)、自动装配BeanFactory)

⭐大有来头?分析AnnotationAwareAspectJAutoProxyCreator

查看AnnotationAwareAspectJAutoProxyCreator继承关系中这些类的方法,找出与后置处理器和Bean工厂有关的方法,打断点观察,包括上面注入的ioc入口、业务和AOP。从父类开始:

  • AbstractAutoProxyCreator(抽象自动代理创建者)
    • AbstractAutoProxyCreator.setBeanFactory()
    • AbstractAutoProxyCreator.有后置处理器的逻辑(postProcessBeforeInstantiation(实例化前的后置处理器))
  • AbstractAdvisorAutoProxyCreator.[重写]setBeanFactory()-->{ initBeanFactory() }
    • 给AbstractAdvisorAutoProxyCreator.setBeanFactory()打上断点
  • AnnotationAwareAspectJAutoProxyCreator.[重写]initBeanFactory()

⭐我注册我?注册AnnotationAwareAspectJAutoProxyCreator

  通过后置处理器注入了一个后置处理器

执行过程

启动程序,首先创建容器

  1. AnnotationConfigApplicationContext传入配置类,创建ioc容器

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

  3. refresh()中有registerBeanPostProcessors(beanFactory)注册bean的后置处理器(注释:注册拦截 Bean 创建的 Bean 处理器),用来拦截bean的创建

  4. 后置处理器的注册逻辑:

  5. beanFactory.getBeanNamesForType()先获取ioc容器已经定义了的需要创建对象的所有BeanPostProcessor(为什么更启动就有已定义的BeanPostProcessor?是因为在启动时有一个注解@EnableAspectJAutoProxy已经注册了一个AnnotationAwareAspectJAutoProxyCreator和容器中其他一些默认的,只是定义还没创建对象,在上面讲过)

    1. 根据获取的postProcessorNames,发现里面有一个org.springframework.aop.config.internalAutoProxyCreator,就是通过@EnableAspectJAutoProxy注册的AnnotationAwareAspectJAutoProxyCreator类型的属性的名字
    2. 接下来按照postProcessorNames来创建对象
    3. beanFactory.addBeanPostProcessor()给容器中加入别的BeanPostProcessor
    4. 通过postProcessorNames判断是否有实现Ordered优先级接口的,分别放在一起分步处理
      1. 优先注册实现了PriorityOrdered接口的BeanPostProcessor
      2. 再给容器中注册实现了Ordered接口的BeanPostProcessor
      3. 注册没实现优先级接口的BeanPostProcessor
      4. 执行每个优先级中的beanFactory.getBean(ppName, BeanPostProcessor.class),跳转到下一调用创建Bean
    5. 注册BeanPostProcessor,实际上就是创建BeanPostProcessor对象,保存在容器中(重要,每次创建Bean都要执行,BeanPostProcessor本质也是Bean)
      0. 下面创建internalAutoProxyCreatorBeanPostProcessor类型是AnnotationAwareAspectJAutoProxyCreator
      1. 创建Bean的实例(先从beanFactory.getBean()获取名字,由getBean()->doGetBean(),在doGetBean()中调getSingleton()获取单实例的bean,第一次没有,所以用singletonFactory.getObject()->createBean()->doCreateBean()->createBeanInstance()创建bean实例,下面进行初始化。如同之前讲过的BeanPostProcessor原理)
      2. populateBean(beanName,mbd,instanceWrapper):给bean的各种属性赋值
      3. initializeBean(beanName,exposedObject,mbd):初始化bean
        1. invokeAwareMethods(beanName,bean):处理Aware接口的方法回调
          1. 先判断是否是BeanFactoryAware类型,然后到达AbstractAutoProxyCreator.setBeanFactory(beanFactory)方法,就是上面分析AnnotationAwareAspectJAutoProxyCreator的父类AbstractAutoProxyCreator
          2. 然后执行initBeanFactory(beanFactory)初始化BeanFacotry
        2. applyBeanPostProcessorsBeforeInitialization():应用后置处理器的postProcessBeforeInitialization()
        3. invokeInitMethods(beanName,wrappedBean,mbd):执行自定义的初始化方法
        4. applyBeanPostProcessorsAfterInitialization():执行后置处理器的postProcessAfterInitialization()
      4. BeanPostProcessor(AnnotationAwareAspectJAutoProxyCreator)创建成功
    6. BeanPostProcessor(AnnotationAwareAspectJAutoProxyCreator)注册到BeanFactory中,beanFactory.addBeanPostProcessor(postProcessor)BeanFactory添加新的BeanPostProcessor
      以上是创建和注册AnnotationAwareAspectJAutoProxyCreator的过程

部分源码

  • 注册后置处理器

    	public static void registerBeanPostProcessors(
    			ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {
    
    		String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);
    
    		// 注册记录信息消息的BeanPostProcessorChecker
    		// bean是在BeanPostProcessor实例化期间创建的
    		// bean不适合被所有BeanPostProcessors处理。
    		int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;
    		beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));
    
    		// 在实现prioritordered、Ordered和其他功能的BeanPostProcessors之间分离。
    		List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<BeanPostProcessor>();
    		List<BeanPostProcessor> internalPostProcessors = new ArrayList<BeanPostProcessor>();
    		List<String> orderedPostProcessorNames = new ArrayList<String>();
    		List<String> nonOrderedPostProcessorNames = new ArrayList<String>();
    		for (String ppName : postProcessorNames) {
    			if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
    				BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
    				priorityOrderedPostProcessors.add(pp);
    				if (pp instanceof MergedBeanDefinitionPostProcessor) {
    					internalPostProcessors.add(pp);
    				}
    			}
    			else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
    				orderedPostProcessorNames.add(ppName);
    			}
    			else {
    				nonOrderedPostProcessorNames.add(ppName);
    			}
    		}
    
    		// 首先,注册实现prioritordered的BeanPostProcessors。
    		sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
    		registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);
    
    		// 接下来,注册实现Ordered的BeanPostProcessors。
    		List<BeanPostProcessor> orderedPostProcessors = new ArrayList<BeanPostProcessor>();
    		for (String ppName : orderedPostProcessorNames) {
    			BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
    			orderedPostProcessors.add(pp);
    			if (pp instanceof MergedBeanDefinitionPostProcessor) {
    				internalPostProcessors.add(pp);
    			}
    		}
    		sortPostProcessors(orderedPostProcessors, beanFactory);
    		registerBeanPostProcessors(beanFactory, orderedPostProcessors);
    
    		// 现在,注册所有常规的BeanPostProcessors。
    		List<BeanPostProcessor> nonOrderedPostProcessors = new ArrayList<BeanPostProcessor>();
    		for (String ppName : nonOrderedPostProcessorNames) {
    			BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
    			nonOrderedPostProcessors.add(pp);
    			if (pp instanceof MergedBeanDefinitionPostProcessor) {
    				internalPostProcessors.add(pp);
    			}
    		}
    		registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors);
    
    		// 最后,重新注册所有内部BeanPostProcessors。
    		sortPostProcessors(internalPostProcessors, beanFactory);
    		registerBeanPostProcessors(beanFactory, internalPostProcessors);
    
    		// 将用于检测内部bean的后处理器重新注册为applicationlistener,
    		// 将它移动到处理器链的末端(用于获取代理等)。
    		beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));
    	}
    
  • 属性赋值与初始化

    		// 初始化bean实例
    		Object exposedObject = bean;
    		try {
    			// 属性赋值
    			populateBean(beanName, mbd, instanceWrapper);
    			if (exposedObject != null) {
    				exposedObject = initializeBean(beanName, exposedObject, mbd);
    			}
    		}
    
  • 初始化BeanFacotry

        public void setBeanFactory(BeanFactory beanFactory) {
            super.setBeanFactory(beanFactory);
            if (!(beanFactory instanceof ConfigurableListableBeanFactory)) {
                throw new IllegalArgumentException("AdvisorAutoProxyCreator requires a ConfigurableListableBeanFactory: " + beanFactory);
            } else {
                //初始化BeanFacotry
               this.initBeanFactory((ConfigurableListableBeanFactory)beanFactory);
            }
        }
    

运行时栈信息

  • beanFactory.getBeanNamesForType()先获取ioc容器已经定义了的需要创建对象的所有BeanPostProcessor

    浅尝Spring注解开发_AOP原理及完整过程分析(源码)-LMLPHP

  • 创建bean

    浅尝Spring注解开发_AOP原理及完整过程分析(源码)-LMLPHP

  • BeanPostProcessor注册到BeanFactory中,给BeanFactory添加BeanPostProcessor

    浅尝Spring注解开发_AOP原理及完整过程分析(源码)-LMLPHP

⭐你比我快?AnnotationAwareAspectJAutoProxyCreator执行时机

  上面代码执行后,注册了AnnotationAwareAspectJAutoProxyCreator,它是一个后置处理器,当其他组件在创建对象时,都要经过创建Bean实例、给Bean属性赋值、初始化及前后处理器,所以它可以拦截到这些组件的创建过程,接下来要看它作为后置处理器都做了什么?

执行流程

接着上面的AbstractAutoProxyCreator.setBeanFactory(beanFactory)执行,然后调用AbstractAutoProxyCreator.postProcessBeforeInstantiation(),注意区分[Smart]InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation()和BeanPostProcessor.postProcessBeforeInitialization(),这一点上面分析AnnotationAwareAspectJAutoProxyCreator时也有提到,为什么会调用这个方法?在整个程序开始时,AnnotationConfigApplicationContext创建ioc容器注册配置,register()调用refresh()刷新容器,上面第(3)步执行的是registerBeanPostProcessors(beanFactory)注册bean的后置处理器方法,在它下面有一个finishBeanFactoryInitialization(beanFactory)方法

  1. finishBeanFactoryInitialization(beanFactory):完成BeanFactory初始化工作,创建剩下的单实例bean

    1. 遍历获取容器中所有的Bean,依次创建对象(这一步还没创建,只是获取,下一步才创建)

      1. DefaultListableBeanFactory.getBean(beanName)->AbstractBeanFactory.getBean()->doGetBean()->getSingleton(beanName, new ObjectFactory<Object>())=>创建Bean实例,返回一个sharedInstance属性,注释是"Create bean instance"(创建bean实例)
      2. 观察之前的代码,发现sharedInstance已经创建Object sharedInstance = getSingleton(beanName)注释是"Eagerly check singleton cache for manually registered singletons(急切地检查单例缓存中是否有手动注册的单例)"
      3. 可以发现Bean不是直接创建出来的
    2. 创建bean

      1. 先从缓存中获取当前bean,如果能获取到,说明bean是之前被创建过的,直接使用,否则再创建。只要创建好的Bean都会被缓存起来

      2. 执行getSingleton(beanName, new ObjectFactory<Object>())参数中的匿名内部类方法

      3. createBean():创建bean

        1. createBean()创建bean包括RootBeanDefinition mbd是bean的定义信息等,继续执行

        2. resolveBeforeInstantiation(beanName, mbdToUse)注释是"Give BeanPostProcessors a chance to return a proxy instead of the target bean instance"(让BeanPostProcessors有机会返回一个代理而不是目标bean实例)

          1. 解析BeforeInstantiation,希望后置处理器在此能返回一个代理对象

          2. 如果能返回代理对象就使用,如果不能就继续,后置处理器先尝试返回对象:

            • 分析:
            • AnnotationAwareAspectJAutoProxyCreator会在任何bean创建之前先尝试返回bean的实例
            • InstantiationAwareBeanPostProcessor是在创建Bean实例之前先尝试用后置处理器返回对象的
            • BeanPostProcessor是在Bean对象创建完成[自定义]初始化前后调用的
            • InstantiationAwareBeanPostProcessor是在构造方法前后执行(就在这一步),BeanPostProcessor是在Bean属性赋值[初始化之后],自定义初始化前后执行(就在下一步)】
            //拿到所有后置处理器,如果是InstantiationAwareBeanPostProcessor就执行postProcessBeforeInstantiation
            bean = applyBeanPostProcessorsBeforeInstantiation():
            if (bean != null) {
                bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
            }
            //------------
            if (bp instanceof InstantiationAwareBeanPostProcessor) {
            	ibp.postProcessBeforeInstantiation(beanClass, beanName);
            }
            
        3. doCreateBean(beanName, mbdToUse, args):真正的去创建一个bean实例,包括createBeanInstance()创建Bean实例、populateBean()属性赋值、initializeBean()初始化Bean、Aware接口、前置后置等,和上一节的(3.4)一样

部分源码

  • 创建一个 Bean 实例

    	/**
    	 * 此类的中心方法:创建一个 Bean 实例,
    	 * 填充 Bean 实例、应用后处理器等。
    	 * @see #doCreateBean
    	 */
    	@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;
    
    		// 确保此时实际解析了 Bean 类,并且
    		// 在动态解析类的情况下克隆 Bean 定义
    		// 不能存储在共享的合并 Bean 定义中。
    		Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
    		if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
    			mbdToUse = new RootBeanDefinition(mbd);
    			mbdToUse.setBeanClass(resolvedClass);
    		}
    
    		// 准备方法覆盖。
    		try {
    			mbdToUse.prepareMethodOverrides();
    		}
    		catch (BeanDefinitionValidationException ex) {
    			throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
    					beanName, "Validation of method overrides failed", ex);
    		}
    
    		try {
    			// 给 BeanPostProcessors 一个返回代理而不是目标 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);
    		}
    		// 实际创建指定的bean
    		Object beanInstance = doCreateBean(beanName, mbdToUse, args);
    		if (logger.isDebugEnabled()) {
    			logger.debug("Finished creating instance of bean '" + beanName + "'");
    		}
    		return beanInstance;
    	}
    
  • 尝试返回一个代理

    	protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
    		Object bean = null;
    		if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
    			// 确保此时实际解析了 Bean 类。
    			if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
    				Class<?> targetType = determineTargetType(beanName, mbd);
    				if (targetType != null) {
    					bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
    					if (bean != null) {
    						bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
    					}
    				}
    			}
    			mbd.beforeInstantiationResolved = (bean != null);
    		}
    		return bean;
    	}
    

运行时栈信息

  • 准备实例化

    浅尝Spring注解开发_AOP原理及完整过程分析(源码)-LMLPHP

⭐你先我后?创建AOP代理

  经过上面的流程,已经知道创建Bean需要调用AnnotationAwareAspectJAutoProxyCreator[类型是InstantiationAwareBeanPostProcessor]的后置处理器,然后才是初始化前后的BeanPostProcessor后置处理器,下面关心在AnnotationAwareAspectJAutoProxyCreator.postProcessBeforeInstantiation()中都做了什么操作

执行过程

  1. 继续上节倒数第二步,进入应用后置处理器中,每一个bean创建之前,调用InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation()
    0. 关心MathCalculator[业务类]LogAspect[切面类]的创建
    1. this.advisedBeans.contaionsKey(cacheKey)判断当前bean是否在advisedBeans中(保存了所有需要增强bean)?现在没有
    2. isInfrastructureClass(beanClass)判断当前bean是否是基础类型的Advice、Pointcut、Advisor、AopInfrastructureBeanthis.aspectJAdvisorFactory.isAspect(beanClass)或者是否是切面(通过有没有@Aspect注解判断)
    3. shouldSkip(beanClass,beanName)是否需要跳过
      1. List<Advisor> candidateAdvisors = findCandidateAdvisors()找到候选的增强器(增强器就是自定义的LogAspect切面中通知方法),每一个封装的通知方法的增强器是 InstantiationModelAwarePointcutAdvisor: expression [pointCut()]; advice method [public void com.atguigu.aop.LogAspects.logStart(org.aspectj.lang.JoinPoint)],判断每一个增强器是否是 AspectJPointcutAdvisor 类型的,是就返回true,现在都不是
  2. 然后创建bean对象后,(在初始化后)执行[AbstractAutoProxyCreator]BeanPostProcessor.postProcessAfterInitialization()
    0. 进入return wrapIfNecessary(bean, beanName, cacheKey)如有必要,就包装,只有被代理类才会创建代理对象
    1. Object[] specificInterceptors=getAdvicesAndAdvisorsForBean(bean.getClass(),beanName,null)注释是Create proxy if we have advice(如果我们有通知方法,请创建代理)获取当前bean的所有增强器(通知方法),进入
      1. findEligibleAdvisors(beanClass,beanName)找到候选的所有的增强器(找哪些通知方法是需要切入当前bean方法的)
      2. 获取到能在bean使用的增强器,如切入点表达式
      3. 给增强器排序
    2. 已经获取到可用增强器,保存当前bean在已增强集合中this.advisedBeans.put()
    3. 如果当前bean需要增强,创建当前bean的代理对象Object proxy = createProxy()
      1. 获取所有增强器(通知方法)
      2. 保存到proxyFactory
      3. 创建代理对象proxyFactory.getProxy(getProxyClassLoader()):Spring自动决定两种方式
        • JdkDynamicAopProxy(config):jdk动态代理(需要接口);
        • ObjenesisCglibAopProxy(config):cglib的动态代理;
      4. 创建完成后得到的bean的增强代理对象
    4. 给容器中返回当前组件使用cglib增强了的代理对象
    5. 以后容器中获取到的就是这个组件的代理对象MathCalculator(业务类)$EnhancerBySpringCGLIB,执行目标方法的时候,代理对象就会执行通知方法的流程

部分源码

  • 如果必要包装

    	//必要时包装给定的bean,即,如果它符合被代理的条件。
    	protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
    		//...
    		// 如果我们有建议,请创建代理。
    		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;
    	}
    
    
  • 创建代理

    	// 创建一个CGLIB代理或JDK动态代理。
    	@Override
    	public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
    		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)) {
    				// 创建JDK动态代理
    				return new JdkDynamicAopProxy(config);
    			}
    			// 创建CGLIB代理
    			return new ObjenesisCglibAopProxy(config);
    		}
    		else {
    			return new JdkDynamicAopProxy(config);
    		}
    	}
    

⭐如此包装?获取拦截器链MethodInterceptor

  接着上面代码执行,在上面已经获取到被代理后的对象,现在需要把所有的增强方法转为MethodInterceptor类型。

执行过程

  1. (被代理后的)目标方法执行:容器中保存了组件的代理对象(cglib增强后的对象),这个对象里面保存了详细信息(比如增强器,目标对象,xxx)

    1. debug 从ioc容器中的目标方法执行开始进入下一步(或者:入-出-出-入-出-入-出-入)

    2. CglibAopProxy.intercept():拦截目标方法的执行

    3. 根据ProxyFactory对象获取将要执行的目标方法拦截器链:List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass)

      1. List<Object> interceptorList = new ArrayList<Object>(config.getAdvisors().length)保存所有拦截器,拦截器列表长度就是config.getAdvisors()长度,等于5。包括一个默认的ExposeInvocationInterceptor 和 4个(自定义)增强器
      2. 遍历所有的增强器,如果是切入点的增强器,将其转为拦截器MethodInterceptorMethodInterceptor[] interceptor = registry.getInterceptors(advisor)
        3. 将增强器转为List<MethodInterceptor>拦截器
        1. 如果是MethodInterceptor,直接加入到集合中
        2. 如果不是,使用AdvisorAdapter将增强器转为MethodInterceptor
          3. 转换完成返回MethodInterceptor数组
    4. 或者本身是Interceptor,或者由其他类型转为MethodInterceptor,最终返回拦截器列表(此次是5个)

  2. 如果没有拦截器链chain.isEmpty(),直接执行目标方法methodProxy.invoke()

    1. 如果有拦截器链,把需要执行的目标对象,目标方法,拦截器链等信息传入创建一个CglibMethodInvocation 对象,并调用 Object retVal = new CglibMethodInvocation(proxy,traget,method,args,targetClass,chain,methodProxy).proceed()继续执行

部分源码

  • 代理对象刚执行时的拦截方法

    		@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) {
    					// 在必要时使调用可用。
    					oldProxy = AopContext.setCurrentProxy(proxy);
    					setProxyContext = true;
    				}
    				// 可能为空。尽可能晚地减少我们“拥有”目标的时间,以防它来自池...
    				target = getTarget();
    				if (target != null) {
    					targetClass = target.getClass();
    				}
    				// 获取拦截器链
    				List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
    				Object retVal;
    				// 检查是否有拦截器链
    				if (chain.isEmpty() && Modifier.isPublic(method.getModifiers())) {
    					// 我们可以跳过创建方法调用:只需直接调用目标即可。请注意,最终的调用程序必须是 InvokerInterceptor,因此我们知道它只对目标执行反射操作,并且没有热插拔或花哨的代理。
    					Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
    					retVal = methodProxy.invoke(target, argsToUse);
    				}
    				else {
    					// 我们需要创建一个方法调用(执行目标方法)...
    					retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();
    				}
    				retVal = processReturnType(proxy, target, method, retVal);
    				return retVal;
    			}
    			//...
    		}
    
  • 包装拦截器

    	@Override
    	public List<Object> getInterceptorsAndDynamicInterceptionAdvice(
    			Advised config, Method method, Class<?> targetClass) {
    
    		// 这有点棘手...我们必须首先处理介绍,但我们需要保持最终列表中的秩序。
    		List<Object> interceptorList = new ArrayList<Object>(config.getAdvisors().length);
    		Class<?> actualClass = (targetClass != null ? targetClass : method.getDeclaringClass());
    		boolean hasIntroductions = hasMatchingIntroductions(config, actualClass);
    		AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();
    
    		for (Advisor advisor : config.getAdvisors()) {
    			if (advisor instanceof PointcutAdvisor) {
    				// 有条件地添加它。
    				PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor;
    				if (config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(actualClass)) {
    					// 转为拦截器
    					MethodInterceptor[] interceptors = registry.getInterceptors(advisor);
    					MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher();
    					if (MethodMatchers.matches(mm, method, actualClass, hasIntroductions)) {
    						if (mm.isRuntime()) {
    							// 在 getInterceptors()方法中创建新的对象实例不是问题,因为我们通常缓存创建的链。
    							for (MethodInterceptor interceptor : interceptors) {
    								interceptorList.add(new InterceptorAndDynamicMethodMatcher(interceptor, mm));
    							}
    						}
    						else {
    							interceptorList.addAll(Arrays.asList(interceptors));
    						}
    					}
    				}
    			}
    			else if (advisor instanceof IntroductionAdvisor) {
    				// ...将其余类型都转为拦截器
    			}
    		return interceptorList;
    	}
    

⭐喵啊?链式调用通知方法

  所有准备都做好了(创建代理,增强器排序(倒序),增强器包装获取拦截器链),现在开始调用通知方法

执行过程

  1. 拦截器链的触发过程:
    1. 如果没有拦截器执行执行目标方法,或者拦截器的索引和拦截器数组-1大小一样(执行到了最后一个拦截器)执行目标方法
    2. 链式获取每一个拦截器,拦截器执行invoke方法,每一个拦截器等待下一个拦截器执行完成返回以后再来执行。拦截器链的机制,保证通知方法与目标方法的执行顺序

5个拦截器(1个默认+4个自定义)的执行顺序

浅尝Spring注解开发_AOP原理及完整过程分析(源码)-LMLPHP

执行上一节最后一步,获取到拦截器链后执行new CglibMethodInvocation(proxy,traget,method,args,targetClass,chain,methodProxy).proceed()proceed()方法

  1. 进入proceed()方法,先判断currentInterceptorIndex索引的值,默认是-1。this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1 -->{return invokeJoinpoint()}
  2. 判断是否有拦截器,如果没有 0 - 1 = -1,正好等于默认值,没有拦截器,就直接执行目标方法(业务)method.invoke(target,args)
  3. 判断是否是否要执行目标方法。程序多次执行,每加载一个拦截器,就+1,直到最后一个拦截器时,this.currentInterceptorIndex=4(从-1到4),判断4 == 5 - 1,拦截器加载完了,开始执行目标方法(业务)。
  4. 开始执行
    1. -1 == 5 - 1 不通过,表示有拦截器,执行this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex),从-1到0,获取第0号拦截器。
    2. 第 [0] 号拦截器是默认拦截器ExposenvocationInterceptor调用invoke(this),参数this就是被代理目标类(业务类)CgliMethodInvocation,进入invoke(this),里面调用mi[MethodInvocation].proceed()这个proceed()就是本节第(1)步的proceed(),每个拦截器都会执行
    3. 获取索引为 [1] 的拦截器AspectJAfterThrowingAdvice前置拦截器->判断->自增->invoke(this)->mi.proceed()
    4. 获取索引为 [2] 的拦截器AfterReturingAdviceInterceptor返回通知拦截器->判断->自增->invoke(this)->mi.proceed()
    5. 获取索引为 [3] 的拦截器AspectJAfterAdvice->判断->自增->invoke(this)->mi.proceed()
    6. 获取索引为 [4] 的拦截器MethodBeforeAdviceInterceptor前置拦截器->判断->自增->invoke(this){ 这里与之前不同,因为是前置通知,所以要在目标方法执行前先执行增强方法,this.advice.before(mi.getMethod(),mi.getArguments(),mi.getThis())此时执行自定义的前置通知 }->mi.proceed()
    7. 执行完最后一个拦截器,满足条件4 = 5 - 1,所以进入判断执行invokeJoinpoint()利用反射执行目标方法(业务),到达底部同时准备返回
  5. 开始返回
  6. 执行完目标方法,返回到第 [3] 个拦截器AspectJAfterAdvice执行最终通知,不管是否有异常finally{ invokeAdviceMethod(getJoinPointMatch(),null,null) }
  7. 继续返回,到第 [2] 个拦截器,AfterReturingAdviceInterceptor执行返回通知,但是目标方法抛了异常,此处代码将异常继续上抛throws Throwable,所以此处不做任何执行,如果没有异常,就正常调用返回通知this.advice.afterReturning()
  8. 继续返回,到第 [1] 个拦截器,AfterReturingAdviceInterceptor执行异常通知,它可以处理异常 catch(Throwable ex){ if(){invokeAdviceMethod(getJoinPointMatch(),null,ex)} throw ex }
  9. 继续返回,自定义增强方法执行完了,执行第 [0] 个默认拦截器
  10. 增强方法执行过程:逆向执行拦截器,到达底部执行目标方法,返回时正向执行增强方法

部分源码

  • 获取拦截器后继续方法调用

    	@Override
    	public Object proceed() throws Throwable {
    		//	我们从 -1 的索引开始,并提前递增。
    		if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
    			return invokeJoinpoint();
    		}
    
    		// 每次将索引自增
    		Object interceptorOrInterceptionAdvice =
    				this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
    		if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
    			// 在此处评估动态方法匹配器:静态部分将已经过评估并发现匹配。
    			InterceptorAndDynamicMethodMatcher dm =
    					(InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
    			if (dm.methodMatcher.matches(this.method, this.targetClass, this.arguments)) {
    				return dm.interceptor.invoke(this);
    			}
    			else {
    				// 动态匹配失败。
    				// 跳过此侦听器并调用链中的下一个侦听器。
    				return proceed();
    			}
    		}
    		else {
    			// 调用这个
    			// 它是一个拦截器,所以我们只需调用它:在构造此对象之前,切入点将进行静态计算。
    			return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
    		}
    	}
    
  • 依次调用拦截器的mi.proceed()

    • 异常通知:AspectJAfterThrowingAdvice

      	@Override
      	public Object invoke(MethodInvocation mi) throws Throwable {
      		try {
      			return mi.proceed();
      		}
      		catch (Throwable ex) {
      			if (shouldInvokeOnThrowing(ex)) {
      				invokeAdviceMethod(getJoinPointMatch(), null, ex);
      			}
      			throw ex;
      		}
      	}
      
    • 返回通知:AspectJAfterReturningAdvice

      	@Override
      	public Object invoke(MethodInvocation mi) throws Throwable {
      		Object retVal = mi.proceed();
      		this.advice.afterReturning(retVal, mi.getMethod(), mi.getArguments(), mi.getThis());
      		return retVal;
      	}
      
    • 后置通知:AspectJAfterAdvice

      	@Override
      	public Object invoke(MethodInvocation mi) throws Throwable {
      		try {
      			return mi.proceed();
      		}
      		finally {
      			invokeAdviceMethod(getJoinPointMatch(), null, null);
      		}
      	}
      
    • 前置通知:AspectJMethodBeforeAdvice

      	@Override
      	public Object invoke(MethodInvocation mi) throws Throwable {
      		this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis() );
      		return mi.proceed();
      	}
      
  • 调完拦截器之后执行目标方法

    • 满足条件执行目标方法

      		//	我们从-1的索引和早期的增量开始。
      		if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
      			return invokeJoinpoint();
      		}
      
    • 然后一层层向上返回拦截器,并处理通知(除了前置通知,因为它已经在目标方法前执行了

    • 如下:它返回到异常通知拦截器,并处理异常

      	@Override
      	public Object invoke(MethodInvocation mi) throws Throwable {
      		try {
      			return mi.proceed();
      		}
      		catch (Throwable ex) {
      			if (shouldInvokeOnThrowing(ex)) {
      				//处理异常
      				invokeAdviceMethod(getJoinPointMatch(), null, ex);
      			}
      			throw ex;
      		}
      	}
      

总结

  1. @EnableAspectJAutoProxy 开启AOP功能
  2. @EnableAspectJAutoProxy 会给容器中注册一个组件AnnotationAwareAspectJAutoProxyCreator
  3. AnnotationAwareAspectJAutoProxyCreator是一个后置处理器
  4. 容器的创建流程:
    1. registerBeanPostProcessors()注册后置处理器,创建AnnotationAwareAspectJAutoProxyCreator对象
    2. finishBeanFactoryInitialization()初始化剩下的单实例bean
      1. 创建业务逻辑组件和切面组件
      2. AnnotationAwareAspectJAutoProxyCreator拦截组件的创建过程
      3. 组件创建完之后,判断组件是否需要增强
        如果是:切面的通知方法,包装成增强器(Advisor);给业务逻辑组件创建一个代理对象(cglib);
  5. 执行目标方法:
    1. 代理对象执行目标方法
    2. CglibAopProxy.intercept()
      1. 得到目标方法的拦截器链(增强器包装成拦截器MethodInterceptor
      2. 利用拦截器的链式机制,依次进入每一个拦截器进行执行;
      3. 效果:
        正常执行:前置通知-》目标方法-》后置通知-》返回通知
        出现异常:前置通知-》目标方法-》后置通知-》异常通知
05-04 19:44