简单了解spring中的BeanPostProcessor(后置处理器)

现象

最近项目中使用了spring中的异步处理@EnableAsync和定时任务@EnableSchedule二者作用在同一个service中,导致异步方法失效,最终发现还是不了解后置处理器作用导致的,还是图样图森破

BeanPostProcessor

该接口的两个方法如下,都与Bean的生命周期有密切联系,
不了解bean生命周期的同学参考

  • postProcessBeforeInitialization()
    这个方法作用于bean的初始化之前,
    • init-method指定的方法
    • 重写InitializingBean接口的afterPropertiesSet()方法
    • @PostConstruct注解标注的方法
  • postProcessAfterInitialization()
    该方法作用于初始化完成之后

源码解读

我们知道,spring的入口在AbstractApplicationContextrefresh()方法中,如图:
refresh方法
其中框起来的方法,就是扫描容器中的BeanPostProcessor过程,在执行到该方法时候,容器中已经默认添加了几个BeanPostProcessor实例对象,注意,是实例。如下图示:
在这里插入图片描述
接下来就是执行registerBeanPostProcessors()方法

public static void registerBeanPostProcessors(
			ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {
		// 从容器中获取所有`BeanPostProcessor`的bean定义
		String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);

		// 注册一个后置处理器检查器,本身也是一个BeanPostProcessor,
		// 当容器的日志级别是info时,打印出没有被所有BeanPostProcessor作用的bean对象
		int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;
		//将这个后置处理器检查器注入到BeanFactory中,所有的bean初始化会遍历bean工厂中的后置处理器集合,作用到每个bean的初始化中
		beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));

		// 将实现了不同接口的后置处理器分别单独处理 ,实现了同一接口的后置处理器属于一类,同一类不能相互作用,优先级的顺序是,PriorityOrdered,Ordered, others
		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);
			}
		}

		// 首先注册实现了PriorityOrdered接口的后置处理器
		sortPostProcessors(beanFactory, priorityOrderedPostProcessors);
		//添加到beanFactory的后置处理器集合中,
		registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);

		//其次,注册实现Ordered接口的后置处理器,注意,ordered越大,优先级越小。
		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(beanFactory, orderedPostProcessors);
	  //添加到beanFactory的后置处理器集合中,
		registerBeanPostProcessors(beanFactory, orderedPostProcessors);

		// 现在,注册一些普通的后置处理器
		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);
			}
		}
		//添加到beanFactory的后置处理器集合中,
		registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors);

		// 最后,重新注册内部后置处理器
		sortPostProcessors(beanFactory, internalPostProcessors);
		registerBeanPostProcessors(beanFactory, internalPostProcessors);

		beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));
	}

以上就是spring对后置处理器的初始化过程,当初始完这些后,refresh()方法中的finishBeanFactoryInitialization()方法,就会继续初始化容器中所有的单例,非懒加载的bean对象,这些对象包含我们自定义的Controller,Service等,这些自定义对象就会按照上面后置处理器的处理逻辑,执行对应的postProcessBeforeInitialization()postProcessAfterInitialization()方法。

结语

由于spring中的异步是通过实现了Ordered接口的AsyncAnnotationBeanPostProcessor处理的,定时任务是通过实现了Ordered接口的ScheduledAnnotationBeanPostProcessor处理的,二者都实现了Order接口,属于同一优先级,由于同一优先级的后置处理器不能相互作用,然后在spring在初始化ScheduledAnnotationBeanPostProcessor后置处理器时,发现某个bean依赖了这个service,导致service被提前加载了,此时实现Ordered接口的后置处理器还没有放到BeanFactory中,故异步功能失效了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章