• 作者:老汪软件技巧
  • 发表时间:2024-08-28 00:02
  • 浏览量:

一、概述

什么是BeanPostProcessor?

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

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

MergedBeanDefinitionPostProcessorDestructionAwareBeanPostProcessor

二、Bean创建 vs BeanPostProcessor

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

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

AbstractAutowireCapableBeanFactory.initializeBean:初始化BeanAbstractAutowireCapableBeanFactory.invokeInitMethods:执行初始化方法,包括BeanPostProcessor.postProcessAfterInitialization:初始化之后执行。Spring AOP功能,大部分场景,就是在这里,对bean进行代理的。AbstractAutowireCapableBeanFactory.registerDisposableBeanIfNecessary:注册销毁方法

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创建的过程中,并不会应用到。

四、如何注册

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

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

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

实现了PriorityOrdered接口的BeanPostProcessor。实现了Ordered接口的BeanPostProcessor。其他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 priorityOrderedPostProcessors = new ArrayList<>();
	List internalPostProcessors = new ArrayList<>();
	List orderedPostProcessorNames = new ArrayList<>();
	List 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 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 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实现了很多功能。