死磕源码系列springboot项目打印is not eligible for getting processed by all BeanPostProcessors (for example: n

2022年8月31日10:15:35

标题上打印的日志是info级别的,不影响程序正常使用,但是有代码洁癖的我还是看着不爽,总想找出问题所在,查了很久知道了是IOC容器注册Bean的时候使用到了还未注册到IOC容器中的Bean,也就是某一些Bean需要提前初始化的原因,后置处理器处理的时候打印了一条日志信息,那有没有解决方案呢?网上搜了一堆堆的都是说打印日志的原因,而没有提供一个有效的解决方案,经过几天巴拉巴拉的翻源码终于找到了两种解决方案,那就看看我们一步步的分析吧(不想看源码分析只想看解决方案的直接拉到最后)。

1.基础知识BeanFactoryPostProcessor和BeanPostProcessor源码分析,及如何实例化并调用BeanFactoryPostProcessor实现类方法修改BeanDefinition
@FunctionalInterfacepublicinterfaceBeanFactoryPostProcessor{/**
	 * 在标准的beanFactory初始化完成后对工厂bean做修改,前提是IOC容器中的所有BeanDefinition已经加载
	 * 完毕,还没有任何Bean进行实例化,这样就可以在bean进行初始化之前对bean的属性进行修改
	 */voidpostProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)throws BeansException;}

Factory钩子接口BeanFactoryPostProcessor会在IOC容器将bean全部加载到容器还没有进行任何实例化之前进行调用,这样我们就可以对BeanDefiniton也就是Bean进行一些属性的修改调整;

publicinterfaceBeanPostProcessor{/**
	 * new bean instance之前调用
	 */@Nullabledefault ObjectpostProcessBeforeInitialization(Object bean, String beanName)throws BeansException{return bean;}/**
	 * new bean instance之后调用
	 */@Nullabledefault ObjectpostProcessAfterInitialization(Object bean, String beanName)throws BeansException{return bean;}

Factory钩子接口BeanPostProcessor会在bean实例化之前和实例化之后分别调用对应的接口;

BeanFactoryPostProcessor接口的实现类会在BeanPostProcessor接口的实现类之前执行,看下springboot refresh方法下源码:

@Overridepublicvoidrefresh()throws BeansException, IllegalStateException{synchronized(this.startupShutdownMonitor){// Prepare this context for refreshing.prepareRefresh();// Tell the subclass to refresh the internal bean factory.
			ConfigurableListableBeanFactory beanFactory=obtainFreshBeanFactory();// Prepare the bean factory for use in this context.prepareBeanFactory(beanFactory);try{// Allows post-processing of the bean factory in context subclasses.postProcessBeanFactory(beanFactory);//实例化并调用所有注册的BeanFactoryPostProcessor bean,如果给定显示顺序,则遵循显示顺序,必须在单例bean实例化之前调用;// Invoke factory processors registered as beans in the context.invokeBeanFactoryPostProcessors(beanFactory);//注册BeanPostProcessor bean 的入口方法// Register bean processors that intercept bean creation.registerBeanPostProcessors(beanFactory);...}

invokeBeanFactoryPostProcessors方法源码

/**
 * Instantiate and invoke all registered BeanFactoryPostProcessor beans,
 * respecting explicit order if given.
 * <p>Must be called before singleton instantiation.
 */
protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
	//此处是实例化并调用BeanFactoryPostProcessor bean的入口
   PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());

   // Detect a LoadTimeWeaver and prepare for weaving, if found in the meantime
   // (e.g. through an @Bean method registered by ConfigurationClassPostProcessor)
   if (beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
      beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
      beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
   }
}

invokeBeanFactoryPostProcessors方法源码如下:

publicstaticvoidinvokeBeanFactoryPostProcessors(
			ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors){// Invoke BeanDefinitionRegistryPostProcessors first, if any.
		Set<String> processedBeans=newHashSet<>();if(beanFactoryinstanceofBeanDefinitionRegistry){
			BeanDefinitionRegistry registry=(BeanDefinitionRegistry) beanFactory;
			List<BeanFactoryPostProcessor> regularPostProcessors=newArrayList<>();
			List<BeanDefinitionRegistryPostProcessor> registryProcessors=newArrayList<>();for(BeanFactoryPostProcessor postProcessor: beanFactoryPostProcessors){if(postProcessorinstanceofBeanDefinitionRegistryPostProcessor){
					BeanDefinitionRegistryPostProcessor registryProcessor=(BeanDefinitionRegistryPostProcessor) postProcessor;
					registryProcessor.postProcessBeanDefinitionRegistry(registry);
					registryProcessors.add(registryProcessor);}else{
					regularPostProcessors.add(postProcessor);}}// Do not initialize FactoryBeans here: We need to leave all regular beans// uninitialized to let the bean factory post-processors apply to them!// Separate between BeanDefinitionRegistryPostProcessors that implement// PriorityOrdered, Ordered, and the rest.
			List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors=newArrayList<>();//首先,调用实现了PriorityOrdered接口的BeanDefinitionRegistryPostProcessors实现类方法// First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered.
			String[] postProcessorNames=
					beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class,true,false);for(String ppName: postProcessorNames){if(beanFactory.isTypeMatch(ppName, PriorityOrdered.class)){
					currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
					processedBeans.add(ppName);}}sortPostProcessors(currentRegistryProcessors, beanFactory);
			registryProcessors.addAll(currentRegistryProcessors);invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
			currentRegistryProcessors.clear();// Next, invoke the BeanDefinitionRegistryPostProcessors that implement Ordered.
			postProcessorNames= beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class,true,false);for(String ppName: postProcessorNames){if(!processedBeans.contains(ppName)&& beanFactory.isTypeMatch(ppName, Ordered.class)){
					currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
					processedBeans.add(ppName);}}sortPostProcessors(currentRegistryProcessors, beanFactory);
			registryProcessors.addAll(currentRegistryProcessors);invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
			currentRegistryProcessors.clear();// Finally, invoke all other BeanDefinitionRegistryPostProcessors until no further ones appear.boolean reiterate=true;while(reiterate){
				reiterate=false;
				postProcessorNames= beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class,true,false);for(String ppName: postProcessorNames){if(!processedBeans.contains(ppName)){
						currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
						processedBeans.add(ppName);
						reiterate=true;}}sortPostProcessors(currentRegistryProcessors, beanFactory);
				registryProcessors.addAll(currentRegistryProcessors);invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
				currentRegistryProcessors.clear();}// Now, invoke the postProcessBeanFactory callback of all processors handled so far.invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);}else{// Invoke factory processors registered with the context instance.invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);}//获取所有BeanFactoryPostProcessor接口实现类bean名称,但是不实例化实现了FactoryBean接口的类// Do not initialize FactoryBeans here: We need to leave all regular beans// uninitialized to let the bean factory post-processors apply to them!
		String[] postProcessorNames=
				beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class,true,false);//将实现了PriorityOrdered接口、实现Ordered接口及其它的BeanFactoryPostProcessors实现类区分开// Separate between BeanFactoryPostProcessors that implement PriorityOrdered,// Ordered, and the rest.
		List<BeanFactoryPostProcessor> priorityOrderedPostProcessors=newArrayList<>();
		List<String> orderedPostProcessorNames=newArrayList<>();
		List<String> nonOrderedPostProcessorNames=newArrayList<>();for(String ppName: postProcessorNames){if(processedBeans.contains(ppName)){// skip - already processed in first phase above}elseif(beanFactory.isTypeMatch(ppName, PriorityOrdered.class)){
				priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));}elseif(beanFactory.isTypeMatch(ppName, Ordered.class)){
				orderedPostProcessorNames.add(ppName);}else{
				nonOrderedPostProcessorNames.add(ppName);}}//首先,调用实现了PriorityOrdered接口的BeanFactoryPostProcessor实现类方法// First, invoke the BeanFactoryPostProcessors that implement PriorityOrdered.sortPostProcessors(priorityOrderedPostProcessors, beanFactory);invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);//接下来,调用实现了Ordered接口的BeanFactoryPostProcessors实现类方法// Next, invoke the BeanFactoryPostProcessors that implement Ordered.
		List<BeanFactoryPostProcessor> orderedPostProcessors=newArrayList<>(orderedPostProcessorNames.size());for(String postProcessorName: orderedPostProcessorNames){//注册BeanFactoryPostProcessors bean
			orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));}sortPostProcessors(orderedPostProcessors, beanFactory);invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);//最后,调用剩余的所有BeanFactoryPostProcessors实现类的方法// Finally, invoke all other BeanFactoryPostProcessors.
		List<BeanFactoryPostProcessor> nonOrderedPostProcessors=newArrayList<>(nonOrderedPostProcessorNames.size());for(String postProcessorName: nonOrderedPostProcessorNames){//注册BeanFactoryPostProcessors bean
			nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));}invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);// Clear cached merged bean definitions since the post-processors might have// modified the original metadata, e.g. replacing placeholders in values...
		beanFactory.clearMetadataCache();}

源码第一部分是BeanDefinitionRegistryPostProcessor接口实现类注册相关实现类到IOC容器之中,不是本文的重点;下一部分是BeanFactoryPostProcessor接口实现类方法,获取不同优先级的BeanFactoryPostProcessor实例对象并调用其实现类方法的代码;

/**
	 * 调用BeanFactoryPostProcessor实现类的postProcessBeanFactory方法,修改BeanDefinition
	 */privatestaticvoidinvokeBeanFactoryPostProcessors(
			Collection<?extendsBeanFactoryPostProcessor> postProcessors, ConfigurableListableBeanFactory beanFactory){for(BeanFactoryPostProcessor postProcessor: postProcessors){
			postProcessor.postProcessBeanFactory(beanFactory);}}
2.registerBeanPostProcessors方法注册BeanPostProcessor实现类的bean实例(打印日志位置查找)
publicstaticvoidregisterBeanPostProcessors(
			ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext){

		String[] postProcessorNames= beanFactory.getBeanNamesForType(BeanPostProcessor.class,true,false);//注册BeanPostProcessorChecker处理器类,此类的方法就是打印信息的位置;也就是当一个bean提前初始化的时候会打印一段info日志信息// 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(newBeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));//分离实现类PriorityOrdered、Ordered接口及其它的BeanPostProcessors实现// Separate between BeanPostProcessors that implement PriorityOrdered,// Ordered, and the rest.
		List<BeanPostProcessor> priorityOrderedPostProcessors=newArrayList<>();
		List<BeanPostProcessor> internalPostProcessors=newArrayList<>();
		List<String> orderedPostProcessorNames=newArrayList<>();
		List<String> nonOrderedPostProcessorNames=newArrayList<>();for(String ppName: postProcessorNames){if(beanFactory.isTypeMatch(ppName, PriorityOrdered.class)){
				BeanPostProcessor pp= beanFactory.getBean(ppName, BeanPostProcessor.class);
				priorityOrderedPostProcessors.add(pp);if(ppinstanceofMergedBeanDefinitionPostProcessor){
					internalPostProcessors.add(pp);}}elseif(beanFactory.isTypeMatch(ppName, Ordered.class)){
				orderedPostProcessorNames.add(ppName);}else{
				nonOrderedPostProcessorNames.add(ppName);}}//首先,注册实例化实现了PriorityOrdered接口的BeanPostProcessors bean// First, register the BeanPostProcessors that implement PriorityOrdered.sortPostProcessors(priorityOrderedPostProcessors, beanFactory);registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);//接下来,注册实例化实现了Ordered接口的BeanPostProcessors bean// Next, register the BeanPostProcessors that implement Ordered.
		List<BeanPostProcessor> orderedPostProcessors=newArrayList<>(orderedPostProcessorNames.size());for(String ppName: orderedPostProcessorNames){
			BeanPostProcessor pp= beanFactory.getBean(ppName, BeanPostProcessor.class);
			orderedPostProcessors.add(pp);if(ppinstanceofMergedBeanDefinitionPostProcessor){
				internalPostProcessors.add(pp);}}sortPostProcessors(orderedPostProcessors, beanFactory);registerBeanPostProcessors(beanFactory, orderedPostProcessors);//现在,注册所有其它BeanPostProcessors bean// Now, register all regular BeanPostProcessors.
		List<BeanPostProcessor> nonOrderedPostProcessors=newArrayList<>(nonOrderedPostProcessorNames.size());for(String ppName: nonOrderedPostProcessorNames){
			BeanPostProcessor pp= beanFactory.getBean(ppName, BeanPostProcessor.class);
			nonOrderedPostProcessors.add(pp);if(ppinstanceofMergedBeanDefinitionPostProcessor){
				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(newApplicationListenerDetector(applicationContext));}
3.BeanPostProcessorChecker类打印提前实例化bean的info信息及解决方案
/**
	 * 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.
	 */privatestaticfinalclassBeanPostProcessorCheckerimplementsBeanPostProcessor{privatestaticfinal Log logger= LogFactory.getLog(BeanPostProcessorChecker.class);privatefinal ConfigurableListableBeanFactory beanFactory;privatefinalint beanPostProcessorTargetCount;publicBeanPostProcessorChecker(ConfigurableListableBeanFactory beanFactory,int beanPostProcessorTargetCount){this.beanFactory= beanFactory;this.beanPostProcessorTargetCount= beanPostProcessorTargetCount;}@Overridepublic ObjectpostProcessBeforeInitialization(Object bean, String beanName){return bean;}@Overridepublic ObjectpostProcessAfterInitialization(Object bean, String beanName){if(!(beaninstanceofBeanPostProcessor)&&!isInfrastructureBean(beanName)&&this.beanFactory.getBeanPostProcessorCount()<this.beanPostProcessorTargetCount){if(logger.isInfoEnabled()){
					logger.info("Bean '"+ beanName+"' of type ["+ bean.getClass().getName()+"] is not eligible for getting processed by all BeanPostProcessors "+"(for example: not eligible for auto-proxying)");}}return bean;}privatebooleanisInfrastructureBean(@Nullable String beanName){if(beanName!= null&&this.beanFactory.containsBeanDefinition(beanName)){
				BeanDefinition bd=this.beanFactory.getBeanDefinition(beanName);return(bd.getRole()== RootBeanDefinition.ROLE_INFRASTRUCTURE);}returnfalse;}}

由上述代码分析可知打印info信息的解决方案两个:

  • 实现BeanPostProcessor接口;
  • 将bean初始化后的BeanDefinition对象的角色更改为2

对于实现BeanPostProcessor接口的解决方案不在展示示例,对第二种解决方案(推荐)示例如下:

publicclassTestBeanPostProcessorimplementsBeanFactoryPostProcessor{@OverridepublicvoidpostProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)throws BeansException{if(beanFactory.containsBeanDefinition(ApiLogAutoConfiguration.class.getName())){
            BeanDefinition beanDefinition= beanFactory.getBeanDefinition
  • 作者:艾米莉Emily
  • 原文链接:https://mingyang.blog.csdn.net/article/details/108628357
    更新时间:2022年8月31日10:15:35 ,共 14509 字。