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

1.基础知识BeanFactoryPostProcessor和BeanPostProcessor源码分析,及如何实例化并调用BeanFactoryPostProcessor实现类方法修改BeanDefinition

@FunctionalInterface
public interface BeanFactoryPostProcessor {/*** 在标准的beanFactory初始化完成后对工厂bean做修改,前提是IOC容器中的所有BeanDefinition已经加载* 完毕,还没有任何Bean进行实例化,这样就可以在bean进行初始化之前对bean的属性进行修改*/void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;}

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

public interface BeanPostProcessor {/*** new bean instance之前调用*/@Nullabledefault Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {return bean;}/*** new bean instance之后调用*/@Nullabledefault Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {return bean;}

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

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

@Overridepublic void refresh() 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方法源码如下:

public static void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {// Invoke BeanDefinitionRegistryPostProcessors first, if any.Set<String> processedBeans = new HashSet<>();if (beanFactory instanceof BeanDefinitionRegistry) {BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {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 = new ArrayList<>();//首先,调用实现了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 = new ArrayList<>();List<String> orderedPostProcessorNames = new ArrayList<>();List<String> nonOrderedPostProcessorNames = new ArrayList<>();for (String ppName : postProcessorNames) {if (processedBeans.contains(ppName)) {// skip - already processed in first phase above}else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));}else if (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 = new ArrayList<>(orderedPostProcessorNames.size());for (String postProcessorName : orderedPostProcessorNames) {//注册BeanFactoryPostProcessors beanorderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));}sortPostProcessors(orderedPostProcessors, beanFactory);invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);//最后,调用剩余的所有BeanFactoryPostProcessors实现类的方法// Finally, invoke all other BeanFactoryPostProcessors.List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size());for (String postProcessorName : nonOrderedPostProcessorNames) {//注册BeanFactoryPostProcessors beannonOrderedPostProcessors.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*/private static void invokeBeanFactoryPostProcessors(Collection<? extends BeanFactoryPostProcessor> postProcessors, ConfigurableListableBeanFactory beanFactory) {for (BeanFactoryPostProcessor postProcessor : postProcessors) {postProcessor.postProcessBeanFactory(beanFactory);}}
2.registerBeanPostProcessors方法注册BeanPostProcessor实现类的bean实例(打印日志位置查找)
 public static void registerBeanPostProcessors(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(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));//分离实现类PriorityOrdered、Ordered接口及其它的BeanPostProcessors实现// 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);}}//首先,注册实例化实现了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 = 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);//现在,注册所有其它BeanPostProcessors bean// 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));}
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.*/private static final class BeanPostProcessorChecker implements BeanPostProcessor {private static final Log logger = LogFactory.getLog(BeanPostProcessorChecker.class);private final ConfigurableListableBeanFactory beanFactory;private final int beanPostProcessorTargetCount;public BeanPostProcessorChecker(ConfigurableListableBeanFactory beanFactory, int beanPostProcessorTargetCount) {this.beanFactory = beanFactory;this.beanPostProcessorTargetCount = beanPostProcessorTargetCount;}@Overridepublic Object postProcessBeforeInitialization(Object bean, String beanName) {return bean;}@Overridepublic Object postProcessAfterInitialization(Object bean, String beanName) {if (!(bean instanceof BeanPostProcessor) && !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;}private boolean isInfrastructureBean(@Nullable String beanName) {if (beanName != null && this.beanFactory.containsBeanDefinition(beanName)) {BeanDefinition bd = this.beanFactory.getBeanDefinition(beanName);return (bd.getRole() == RootBeanDefinition.ROLE_INFRASTRUCTURE);}return false;}}

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

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

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

public class TestBeanPostProcessor implements BeanFactoryPostProcessor {@Overridepublic void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {if (beanFactory.containsBeanDefinition(ApiLogAutoConfiguration.class.getName())) {BeanDefinition beanDefinition = beanFactory.getBeanDefinition(ApiLogAutoConfiguration.class.getName());//修改bean的角色为spring框架级别的beanbeanDefinition.setRole(2);}}
}

springboot角色一共有三种如下:

public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement {/*** 应用程序的重要组成部分,通常指用户自定义bean*/int ROLE_APPLICATION = 0;/*** 应用程序的从配置文件读取到的bean*/int ROLE_SUPPORT = 1;/*** 是spring框架级别的bean*/int ROLE_INFRASTRUCTURE = 2;
}

GitHub地址:https://github.com/mingyang66/spring-parent/tree/master/doc/base

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

  1. 死磕源码系列【springboot之ConditionEvaluationReport记录报告和日志条件评估详情源码解析】

    ConditionEvaluationReport用来记录自动化配置过程中条件匹配的详细信息及日志信息: 1.ConditionOutcome类输出条件匹配及日志信息 public class Con ...

  2. 死磕 java同步系列之ReentrantReadWriteLock源码解析

    问题 (1)读写锁是什么? (2)读写锁具有哪些特性? (3)ReentrantReadWriteLock是怎么实现读写锁的? (4)如何使用ReentrantReadWriteLock实现高效安全的 ...

  3. phaser java_死磕 java同步系列之Phaser源码解析

    问题 (1)Phaser是什么? (2)Phaser具有哪些特性? (3)Phaser相对于CyclicBarrier和CountDownLatch的优势? 简介 Phaser,翻译为阶段,它适用于这 ...

  4. 【免费赠送源码】Springboot科研项目管理系统3lk11计算机毕业设计-课程设计-期末作业-毕设程序代做

    [免费赠送源码]Springboot科研项目管理系统3lk11计算机毕业设计-课程设计-期末作业-毕设程序代做 [免费赠送源码]Springboot科研项目管理系统3lk11计算机毕业设计-课程设计- ...

  5. 死磕 java同步系列之redis分布式锁进化史

    问题 (1)redis如何实现分布式锁? (2)redis分布式锁有哪些优点? (3)redis分布式锁有哪些缺点? (4)redis实现分布式锁有没有现成的轮子可以使用? 简介 Redis(全称:R ...

  6. java任务流程_死磕 java线程系列之线程池深入解析——普通任务执行流程

    (手机横屏看源码更方便) 注:java源码分析部分如无特殊说明均基于 java8 版本. 注:线程池源码部分如无特殊说明均指ThreadPoolExecutor类. 简介 前面我们一起学习了Java中 ...

  7. java 同步锁_死磕 java同步系列之自己动手写一个锁Lock

    问题 (1)自己动手写一个锁需要哪些知识? (2)自己动手写一个锁到底有多简单? (3)自己能不能写出来一个完美的锁? 简介 本篇文章的目标一是自己动手写一个锁,这个锁的功能很简单,能进行正常的加锁. ...

  8. 死磕java_死磕 java同步系列之AQS终篇(面试)

    问题 (1)AQS的定位? (2)AQS的重要组成部分? (3)AQS运用的设计模式? (4)AQS的总体流程? 简介 AQS的全称是AbstractQueuedSynchronizer,它的定位是为 ...

  9. 死磕 java同步系列之AQS起篇

    问题 (1)AQS是什么? (2)AQS的定位? (3)AQS的实现原理? (4)基于AQS实现自己的锁? 简介 AQS的全称是AbstractQueuedSynchronizer,它的定位是为Jav ...

最新文章

  1. 微软牛津计划-语音转文本-文本转语音代码和实现
  2. UE4 custom depth 自定义深度
  3. HDU4473_Exam
  4. 线性表的动态顺序存储和实现(C语言实现)【线性表】(4)
  5. boost::with_lock_guard相关的测试程序
  6. 笔记本软件页面分辨率低_AMD宠粉日 适合设计师的高色域笔记本电脑
  7. Javascript中类型的判断
  8. tornado基本使用一
  9. CICD详解(九)——gitlab简单使用
  10. 玩转Metasploit系列(第二集)
  11. 第一章 批判性思维概念
  12. 树莓派ubuntu默认用户名密码及密码修改
  13. maria安装包mysql_mariadb安装
  14. python sorted lambda_详解python中的lambda与sorted函数
  15. 服务器虚拟化集群部署
  16. Windows下Pidgin介绍/安装配置图文攻略
  17. 互联网数仓之:Lambda架构 vs Kappa架构
  18. 语音通信64K的由来
  19. 航海王热血航线服务器维护怎么办,航海王热血航线无法登录怎么办
  20. 基于Yolov5的草莓病虫害检测识别

热门文章

  1. 新西兰公司注册流程概括
  2. mysql取当天0点0分下一天0点0分_SQL获取当天0点0分0秒和23点59分59秒方法
  3. oracle数据库服务器02
  4. Hystrix 1.5 滑动窗口实现原理总结
  5. 别过来,过来我就撕票了!
  6. 事件分发机制Android,宅家36天咸鱼翻身入职腾讯,复习指南
  7. html字符串自动加回车换行,【HTML】处理br换行符追加到前端换行无效的问题 --- html中渲染的字符串中包含HTML标签无效的处理方法,字符串中包含HTML标签被转义的问题 解决...
  8. Android修改主机名和IP地址问题
  9. 有光就可以上网?中国工程院院士表示,可见光通信要比5G快10倍!
  10. PVM58N-YY1AGR0BN-1213光电采样编码器