BeanPostProcessor——Spring IOC系列(二)

406 阅读6分钟

一、概述

🤔什么是BeanPostProcessor?

BeanPostProcessor是spring提供的一个扩展接口,可以在Bean的实例化、配置、销毁前后,做一些扩展处理。Spring很多bean的相关操作,都是通过BeanPostProcessor实现的。

BeanPostProcessor是一个基础接口,他还有四个扩展接口:

  • InstantiationAwareBeanPostProcessor
    • SmartInstantiationAwareBeanPostProcessor
  • MergedBeanDefinitionPostProcessor
  • DestructionAwareBeanPostProcessor

SmartInstantiationAwareBeanPostProcessor.png

二、Bean创建 vs BeanPostProcessor

在上一章中,我们梳理的Bean的创建流程,源码中充斥着各种BeanPostProcessor。下图描述了,在Bean创建过程中,都触发了哪些BeanPostProcessor。

bean创建&BeanPostProcessor.png

结合源码,梳理下创建过程中,BeanPostProcessor是在哪里执行,你可以结合以下代码骨干,对源码进行进一步的分析。 AbstractAutowireCapableBeanFactory.createBean

  • InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation:在doCreateBean执行之前,如果return的不是null,则直接返回这个bean,不会执行doCreateBean了;
  • AbstractAutowireCapableBeanFactory.doCreateBean
    • AbstractAutowireCapableBeanFactory.createBeanInstance:创建对象实例
      • SmartInstantiationAwareBeanPostProcessor.determineCandidateConstructors:创建之前调用,可以选择使用哪个构造器
      • MergedBeanDefinitionPostProcessor.postProcessMergedBeanDefinition:实例化之后,注入属性之前,每个BeanDefinition仅执行一次。可以改变RootBeanDefinition,比如可以把@Value/@Autowired注解修饰的属性或方法元数据信息缓存下来,留着后续使用。
      • AbstractAutowireCapableBeanFactory.populateBean:注入属性
        • InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation:在真正注入属性之前调用,返回false则停止注入,直接返回
        • InstantiationAwareBeanPostProcessor.postProcessProperties,在属性注入前执行,可以修改或者校验属性。PS:AutowiredAnnotationBeanPostProcessor,在这里对Autowired的属性进行注入。
        • InstantiationAwareBeanPostProcessor.postProcessPropertyValues:已经被标记废弃,建议使用postProcessProperties替代。
      • AbstractAutowireCapableBeanFactory.initializeBean:初始化Bean
        • AbstractAutowireCapableBeanFactory.invokeAwareMethods:为实现BeanNameAware、BeanClassLoaderAware、BeanFactoryAware接口的Bean,注入BeanName/ClassLoader/BeanFactory等属性。
        • BeanPostProcessor.postProcessBeforeInitialization:初始化之前调用。
          • 除上一步的三个Aware接口外,其余的Aware也是在这里处理的
          • 被@PostConstruct修饰的方法调用,也是通过该接口实现的
        • AbstractAutowireCapableBeanFactory.invokeInitMethods:执行初始化方法,包括
          • 实现InitializingBean接口的afterPropertiesSet方法
          • xml或者@Bean注解配置的init-method方法
        • BeanPostProcessor.postProcessAfterInitialization:初始化之后执行。Spring AOP功能,大部分场景,就是在这里,对bean进行代理的。
      • AbstractAutowireCapableBeanFactory.registerDisposableBeanIfNecessary:注册销毁方法
        • DisposableBeanAdapter.hasApplicableProcessors
          • DestructionAwareBeanPostProcessor#requiresDestruction:判断给定的Bean示例,是否需要该BeanPostProcessor销毁。

🤔getEarlyBeanReference呢?

是不是感觉哪里不对,getEarlyBeanReference方法呢,看doCreateBean方法时,好像是看到了该方法的调用。

// Eagerly cache singletons to be able to resolve circular references
// even when triggered by lifecycle interfaces like BeanFactoryAware.
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
        isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
    if (logger.isTraceEnabled()) {
        logger.trace("Eagerly caching bean '" + beanName +
                "' to allow for resolving potential circular references");
    }
    addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}

以上代码来自于doCreateBean方法,确实出现了getEarlyBeanReference,然而,是被作为lambda表达式中调用的。也就是说,这里并不会调用。

那getEarlyBeanReference在哪里调用呢?

是在调用BeanFactory的getBean方法时,尝试从缓存中,获取单例Bean的时,如果出现了循环依赖,需要提前获取Bean时,才会调用。这也是八股文,spring如何解决循环依赖的核心代码。

protected Object getSingleton(String beanName, boolean allowEarlyReference) {
    // Quick check for existing instance without full singleton lock
    Object singletonObject = this.singletonObjects.get(beanName);
    if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
        singletonObject = this.earlySingletonObjects.get(beanName);
        if (singletonObject == null && allowEarlyReference) {
            synchronized (this.singletonObjects) {
                // Consistent creation of early reference within full singleton lock
                singletonObject = this.singletonObjects.get(beanName);
                if (singletonObject == null) {
                    singletonObject = this.earlySingletonObjects.get(beanName);
                    if (singletonObject == null) {
                        ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
                        if (singletonFactory != null) {
                            singletonObject = singletonFactory.getObject();
                            this.earlySingletonObjects.put(beanName, singletonObject);
                            this.singletonFactories.remove(beanName);
                        }
                    }
                }
            }
        }
    }
    return singletonObject;
}

三、其他BeanPostProcessor方法

还有些其他的BeanPostProcessor的方法,在Bean创建的过程中,并不会应用到。

  • SmartInstantiationAwareBeanPostProcessor#predictBeanType : 官方的注释为,预测该处理器的postProcessBeforeInstantiation回调函数最终返回的bean的类型。在BeanFactory的getType方法中,会被调用到。不太清除哪里会使用到。
  • MergedBeanDefinitionPostProcessor#resetBeanDefinition :Bean的定义信息被重置(删除或者替换)时,需要重置缓存的BeanDefinition的元数据信息。MergedBeanDefinitionPostProcessor的另一个方法为postProcessMergedBeanDefinition,仅一个BeanDefinition仅执行一次,部分的postProcessMergedBeanDefinition实现类通过该方法缓存Bean的元数据信息,如果定义被删除或者替换,则也需要删除相关的元数据信息,否则还会使用旧的元数据信息。
  • DestructionAwareBeanPostProcessor#postProcessBeforeDestruction : 在Bean的销毁方法前执行,@PreDestroy就是InitDestroyAnnotationBeanPostProcessor通过该方法实现的。

四、如何注册

🤔实现了BeanPostProcessor,如何注册到ApplicationContext中呢

只要注册为Bean(无论使用哪种手段),会被自动识别为BeanPostProcessor,当然也可以手动直接调用BeanFactory.addBeanPostProcessor来添加BeanPostProcessor。具体代码都在PostProcessorRegistrationDelegate.registerBeanPostProcessors中 。

注意 乍一看,这里的代码好乱,貌似可以稍微优化一下,不过代码里特意注释了一下,不要瞎改这里的代码,写的这么乱是有原因的。BeanPostProcessor需要按照一定的顺序,分批实例化,再注册到BeanFactory中,顺序如下

  1. 实现了PriorityOrdered接口的BeanPostProcessor。
  2. 实现了Ordered接口的BeanPostProcessor。
  3. 其他BeanPostProcessor。

不可以不按照顺序实例化(调用getBean)、注册到BeanFactory。因为BeanPostProcessor,也是一个Bean,在实例化时,也应该被BeanPostProcessor处理,也就是说,实现了Ordered(且没实现PriorityOrdered)接口的BeanPostProcessor,应该被实现了PriorityOrdered的BeanPostProcessor进行处理。而PriorityOrdered这个接口,一般也是spring内部使用的,用于标识一些比较重要的实现类,优先实例化并注册到BeanFactory中,以处理其他Bean。

从源码中可以看到,@Order注解在这里没有被使用到,是无效的,BeanPostProcessor接口的注释中,也提到了这一点。

public static void registerBeanPostProcessors(
		ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {

	// WARNING: Although it may appear that the body of this method can be easily
	// refactored to avoid the use of multiple loops and multiple lists, the use
	// of multiple lists and multiple passes over the names of processors is
	// intentional. We must ensure that we honor the contracts for PriorityOrdered
	// and Ordered processors. Specifically, we must NOT cause processors to be
	// instantiated (via getBean() invocations) or registered in the ApplicationContext
	// in the wrong order.
	//
	// Before submitting a pull request (PR) to change this method, please review the
	// list of all declined PRs involving changes to PostProcessorRegistrationDelegate
	// to ensure that your proposal does not result in a breaking change:
	// https://github.com/spring-projects/spring-framework/issues?q=PostProcessorRegistrationDelegate+is%3Aclosed+label%3A%22status%3A+declined%22

	String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);

	// Register BeanPostProcessorChecker that logs an info message when
	// a bean is created during BeanPostProcessor instantiation, i.e. when
	// a bean is not eligible for getting processed by all BeanPostProcessors.
	// 理论上,在BeanPostProcessor的注册过程中,不该有BeanPostProcessor以外类型实例化,BeanPostProcessorChecker就是负责检查这种情况,如果出现,就打印info日志
	int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;
	beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));

	// Separate between BeanPostProcessors that implement PriorityOrdered,
	// Ordered, and the rest. 把BeanPostProcessor的名字分成三类,实现PriorityOrdered、实现Ordered的和其他
	List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
	List<BeanPostProcessor> internalPostProcessors = new ArrayList<>();
	List<String> orderedPostProcessorNames = new ArrayList<>();
	List<String> nonOrderedPostProcessorNames = new ArrayList<>();
	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);
		}
	}

	// First, register the BeanPostProcessors that implement PriorityOrdered.
	sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
	registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);

	// Next, register the BeanPostProcessors that implement Ordered.
	List<BeanPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size());
	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);

	// Now, register all regular BeanPostProcessors.
	List<BeanPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size());
	for (String ppName : nonOrderedPostProcessorNames) {
		BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
		nonOrderedPostProcessors.add(pp);
		if (pp instanceof MergedBeanDefinitionPostProcessor) {
			internalPostProcessors.add(pp);
		}
	}
	registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors);

	// Finally, re-register all internal BeanPostProcessors.
	// 最后,把实现了MergedBeanDefinitionPostProcessor的,重新注册,放在最后,保证最后运行
	// 重复调用addBeanPostProcessor也没关系,会先移除,在加进去
	sortPostProcessors(internalPostProcessors, beanFactory);
	registerBeanPostProcessors(beanFactory, internalPostProcessors);

	// Re-register post-processor for detecting inner beans as ApplicationListeners,
	// moving it to the end of the processor chain (for picking up proxies etc).
	// 重新注册ApplicationListenerDetector,保证在最后,这样ApplicationListenerDetector才能获取到最终被代理过的Bean
	beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));
}

五、应用

Spring内部就使用BeanPostProcessor实现了很多功能。

  • ApplicationContextAwareProcessor - 通过BeanPostProcessor#postProcessBeforeInitialization方法实现了例如 EnvironmentAware, EmbeddedValueResolverAware, ResourceLoaderAware等aware接口的支持,不过这个不是在registerBeanPostProcessors方法中统一注册的,而是在之前的prepareBeanFactory方法中,就硬编码注册了,这样保证最先注册,可以保证其他的Bean都被ApplicationContextAwareProcessor处理。
  • AutowiredAnnotationBeanPostProcessor - 实现了对@Autowired/@Value/@Lookup/@Inject注解的支持;
  • CommonAnnotationBeanPostProcessor - 实现了对例如@Resource这样的JSR-250注解的支持;
  • InitDestroyAnnotationBeanPostProcessor 实现了对@PostConstruct & @PreDestroy 注解的支持,另外CommonAnnotationBeanPostProcessor继承自InitDestroyAnnotationBeanPostProcessor;
  • AnnotationAwareAspectJAutoProxyCreator 实现spring AOP 动态代理创建的BeanPostProcessor