【SpringCooking】厨师就位(五)refresh方法之registerBeanPostProcessors()

文章详细介绍了Spring如何注册BeanPostProcessor,包括PriorityOrdered和Ordered接口的处理,以及BeanFactoryPostProcessor的区别。通过源码分析了注册过程,强调了注册顺序和执行顺序的重要性,并提供了示例代码说明BeanPostProcessor的作用。
摘要由CSDN通过智能技术生成

1. 背景介绍

在上一篇文章【SpringCooking】厨师就位(四)refresh方法之 invokeBeanFactoryPostProcessors() 中,介绍了 BeanFactoryPostProcessors 的功能以及执行过程。

在另一篇文章【SpringCooking】处理食材(一)ConfigurationClassPostProcessor解析配置类中,介绍了 ConfigurationClassPostProcessor 是如何解析配置类,注册相关组件的 BeanDefinition 的。

经过上面两篇文章的讲解,厨师(BeanFactory)已经利用刀具(BeanFactoryPostProcessor)处理好食材,现在需要准备锅具(BeanPostProcessor)开始烹饪了。

所以本篇文章就来看下,Spring 是怎么帮我们注册 BeanPostProcessor 的。对,你没看错,还是叫了 PostProcessorRegistrationDelegate 这个苦命佬来帮忙干活。

执行 BeanFactoryPostProcessor 也是委托给 PostProcessorRegistrationDelegate 的

public abstract class AbstractApplicationContext extends DefaultResourceLoader
		implements ConfigurableApplicationContext {
		
	protected void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) {
		PostProcessorRegistrationDelegate.registerBeanPostProcessors(beanFactory, this);
	}
}

2. 学习目标

  1. 了解 BeanPostProcessor 的功能
  2. 了解常见的 BeanPostProcessor
  3. 清楚 BeanPostProcessor 的注册流程
  4. 能区分 BeanPostProcessor 和 BeanFactoryPostProcessor 的异同

3. 关键问题

4. 源码追踪

BeanPostProcessor

Factory hook that allows for custom modification of new bean instances — for example, checking for marker interfaces or wrapping beans with proxies.

Typically, post-processors that populate beans via marker interfaces or the like will implement postProcessBeforeInitialization, while post-processors that wrap beans with proxies will normally implement postProcessAfterInitialization.

Registration
An ApplicationContext can autodetect BeanPostProcessor beans in its bean definitions and apply those post-processors to any beans subsequently created. A plain BeanFactory allows for programmatic registration of post-processors, applying them to all beans created through the bean factory.

Ordering
BeanPostProcessor beans that are autodetected in an ApplicationContext will be ordered according to org.springframework.core.PriorityOrdered and org.springframework.core.Ordered semantics. In contrast, BeanPostProcessor beans that are registered programmatically with a BeanFactory will be applied in the order of registration; any ordering semantics expressed through implementing the PriorityOrdered or Ordered interface will be ignored for programmatically registered post-processors. Furthermore, the @Order annotation is not taken into account for BeanPostProcessor beans.

Factory hook,主要作用于自定义修改新bean实例。例如,检查标记接口或着用代理类包装bean

通常,通过标记接口等填充bean的后置处理器将实现postProcessBeforeInitialization,而使用代理包装bean的后处理器通常将实现postProcessAfterInitialization

ApplicationContext可以在其bean定义中自动检测BeanPostProcessor bean,并将这些后处理器应用于随后创建的任何bean。普通的BeanFactory允许后处理程序的编程注册,将它们应用到通过bean工厂创建的所有bean

public interface ConfigurableBeanFactory extends HierarchicalBeanFactory, SingletonBeanRegistry {
	void addBeanPostProcessor(BeanPostProcessor beanPostProcessor);
}

ApplicationContext 会先检测实现了 PriorityOrdered 接口的 BeanPostProcessor ,然后再检测实现了 Ordered 接口的 BeanPostProcessor

而通过 ConfigurableBeanFactory 编码注册的 BeanPostProcessor,则是按照注册的顺序进行执行的,并不会理会是否实现了 PriorityOrdered 或 Ordered

此外,BeanPostProcessor 也不会考虑 @Order注解

排序的特点与 BeanFactoryPostProcessor 一致

综上,BeanPostProcessor 有以下特点:

  1. 与 Bean 交互
  2. 可通过 ConfigurableBeanFactory 手动注册,并且执行的顺序与注册的顺序一致
  3. ApplicationContext 自动检测实现了 PriorityOrdered 和 Ordered 的BeanPostProcessor
  4. @Order 注解在 BeanPostProcessor 的执行顺序上不起效
public interface BeanPostProcessor {

	/**
	 * Apply this {@code BeanPostProcessor} to the given new bean instance <i>before</i> any bean
	 * initialization callbacks (like InitializingBean's {@code afterPropertiesSet}
	 * or a custom init-method). The bean will already be populated with property values.
	 * The returned bean instance may be a wrapper around the original.
	 * <p>The default implementation returns the given {@code bean} as-is.
	 * @param bean the new bean instance
	 * @param beanName the name of the bean
	 * @return the bean instance to use, either the original or a wrapped one;
	 * if {@code null}, no subsequent BeanPostProcessors will be invoked
	 * @throws org.springframework.beans.BeansException in case of errors
	 * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet
	 */
	@Nullable
	default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
		return bean;
	}

	/**
	 * Apply this {@code BeanPostProcessor} to the given new bean instance <i>after</i> any bean
	 * initialization callbacks (like InitializingBean's {@code afterPropertiesSet}
	 * or a custom init-method). The bean will already be populated with property values.
	 * The returned bean instance may be a wrapper around the original.
	 * <p>In case of a FactoryBean, this callback will be invoked for both the FactoryBean
	 * instance and the objects created by the FactoryBean (as of Spring 2.0). The
	 * post-processor can decide whether to apply to either the FactoryBean or created
	 * objects or both through corresponding {@code bean instanceof FactoryBean} checks.
	 * <p>This callback will also be invoked after a short-circuiting triggered by a
	 * {@link InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation} method,
	 * in contrast to all other {@code BeanPostProcessor} callbacks.
	 * <p>The default implementation returns the given {@code bean} as-is.
	 * @param bean the new bean instance
	 * @param beanName the name of the bean
	 * @return the bean instance to use, either the original or a wrapped one;
	 * if {@code null}, no subsequent BeanPostProcessors will be invoked
	 * @throws org.springframework.beans.BeansException in case of errors
	 * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet
	 * @see org.springframework.beans.factory.FactoryBean
	 */
	@Nullable
	default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
		return bean;
	}

}

registerBeanPostProcessors()

分了四种 BeanPostProcessor 进行注册

  1. 实现了 PriorityOrdered 的 BeanPostProcessor
  2. 实现了 Ordered 的 BeanPostProcessor
  3. 普通 BeanPostProcessor
  4. MergedBeanDefinitionPostProcessor

注册前,我们看下 BeanFactory 已经包含了哪些 BeanPostProcessor

beanPostProcessor注册时机
ApplicationContextAwareProcessorrefresh() 的prepareBeanFactory()
ApplicationListenerDetectorrefresh() 的prepareBeanFactory()
ConfigurationClassPostProcessor$ImportAwareBeanPostProcessorConfigurationClassProcessor.postProcessBeanDefinitionRegistry()

再观察 BeanFactory.beanDefinitionMap 中属于 BeanPostProcessor 的 BeanDefinition

beanNamebeanClass
org.springframework.context.annotation.internalAutowiredAnnotationProcessorAutowiredAnnotationBeanPostProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessorCommonAnnotationBeanPostProcessor

这两个 BeanPostProcessor 的 BeanDefinition 同 ConfigurationClassPostProcessor, EventListenerMethodProcessor, DefaultEventListenerFactory 的 BeanDefinition,是在前面 AnnotatedBeanDefinitionReader 初始化的时候,通过 AnnotationConfigUtils.registerAnnotationConfigProcessors() 注册的,具体可参考 【Spring cooking】厨师就位(一)AnnotationConfigApplicationContext

注册过程

  1. 注册 BeanPostProcessorChecker

    BeanPostProcessor 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.

  2. 检测并注册实现了 PriorityOrdered 的 BeanPostProcessor(排序后注册)

  3. 检测并注册实现了 Ordered 的 BeanPostProcessor(排序后注册)

  4. 检测并注册普通 BeanPostProcessor(不排序直接注册)

  5. 重新注册 MergedBeanDefinitionPostProcessor(排序后注册)

  6. 重新注册 ApplicationListenerDetector,使其排在最后,用于检测内部 bean 是否为 ApplicationListener

需要注意的是,这里的注册不是注册 BeanPostProcessors 的 BeanDefinition,而是将 BeanPostProcessor 添加到 DefaultListableBeanFactory.beanPostProcessors

在执行完 registerBeanPostProcessors() 后,DefaultListableBeanFactory.beanPostProcessors 存在的六个 BeanPostProcessors 及其排序如下:

OrderBeanPostProcessorFunction
1ApplicationContextAwareProcessor为实现 EnvironmentAware, EmbeddedValueResolverAware, ResourceLoaderAware, ApplicationEventPublisherAware, MessageSourceAware, and/or ApplicationContextAware 注入 ApplicationContext, Environment, StringValueResolver
2ConfigurationClassPostProcessor$ImportAwareBeanPostProcessor处理实现 ImportAware 的Bean,注入 importingBean
3PostProcessorRegistrationDelegate$BeanPostProcessorChecker当 bean 没有被所有 beanPostProcessor 处理时,记录日志
4CommonAnnotationBeanPostProcessor处理 @PostConstruct, @PreDestroy等等注解
5AutowiredAnnotationBeanPostProcessor处理 @Autowired, @Value 注解
6ApplicationListenerDetector检测实现 ApplicationListener 接口的 bean
0 = {ApplicationContextAwareProcessor} 
1 = {ConfigurationClassPostProcessor$ImportAwareBeanPostProcessor} 
2 = {PostProcessorRegistrationDelegate$BeanPostProcessorChecker} 
3 = {CommonAnnotationBeanPostProcessor} 
4 = {AutowiredAnnotationBeanPostProcessor} 
5 = {ApplicationListenerDetector} 
final class PostProcessorRegistrationDelegate {

	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.
		int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;
		beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));

		// Separate between BeanPostProcessors that implement PriorityOrdered,
		// Ordered, and the rest.
		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.
		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).
		beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));
	}
}

5. 结论

6. 注意细节

  1. BeanPostProcesscor 同样会作用于将要注册的 BeanPostProcessor

    定义一个实现 PriorityOrdered 的 MyBeanPostProcessor,它将在 CustomBeanPostProcessor 实例化前打印出其 className

    public class MyBeanPostProcessor implements BeanPostProcessor, PriorityOrdered {
    
        public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
            System.out.println(bean.getClass());
            return bean;
        }
    
        public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
            return bean;
        }
    
        @Override
        public int getOrder() {
            return 0;
        }
    }
    
    public class CustomBeanPostProcessor implements BeanPostProcessor {
    
        @Value("${username}")
        private String username;
    
        public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
            System.out.println(username);
            return bean;
        }
    
        public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
            return bean;
        }
    }
    

    我猜测这也是为什么四种 BeanPostProcessor 的存储集合,只有 priorityOrderedPostProcessors 存的是 BeanPostProcessor ,其余的存都是 beanName。如果其余存的是 BeanPostProcessor ,当在分类的时候就 getBean 去实例化 BeanPostProcessor,priorityOrderedPostProcessors 不一定能作用于其他的 BeanPostProcessor。

    List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
    List<String> orderedPostProcessorNames = new ArrayList<>();
    List<String> nonOrderedPostProcessorNames = new ArrayList<>();
    

7. 待研究

  1. 为什么 internalPostProcessors 需要往后排
  2. 为什么 ApplicationListenerDetector 需要排在最后

8. 推荐文章

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值