前言

上一篇文章我们聊了一下自定义实现的SPI如何与spring进行整合,但其实在实现的过程中有个小细节,就是原先我们的SPI是带了拦截器功能,(ps:对如何实现一个带拦截器的SPI感兴趣的朋友,可以查看这篇文章–>聊聊如何实现一个带有拦截器功能的SPI)。

为了保留这个拦截器功能,我原先的想法是狸猫换太子,在spring提供的后置处理器里面,把拦截器功能给整合进去,当时的实现代码如下

@Slf4j
@Deprecated
public class SpiInstancePostProcessor implements BeanPostProcessor {private DefaultListableBeanFactory beanFactory;private InterceptorHandler interceptorHandler;public SpiInstancePostProcessor(InterceptorHandler interceptorHandler,DefaultListableBeanFactory beanFactory) {this.interceptorHandler = interceptorHandler;this.beanFactory = beanFactory;}@SneakyThrows@Overridepublic Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {if(bean.getClass().isAnnotationPresent(Activate.class)){return interceptorHandler.getInterceptorChain().pluginAll(bean);}return bean;}}

功能是实现了,但是控制台却出现如下信息

trationDelegate$BeanPostProcessorChecker : Bean ‘interceptorHandler’ of type [com.github.lybgeek.spring.interceptor.handler.InterceptorHandler] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)

排查过程

当时排查是通过控制提示的信息,找到对应源码。在

org.springframework.context.support.PostProcessorRegistrationDelegate

找到相应的实现

@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;}

看到这个信息,按正常做法是让

!(bean instanceof BeanPostProcessor) && !isInfrastructureBean(beanName) &&this.beanFactory.getBeanPostProcessorCount() < this.beanPostProcessorTargetCount

这个语句块为false,从代码我们很容易看出语句块为false,有几个入口

  1. !(bean instanceof BeanPostProcessor)
  2. !isInfrastructureBean(beanName)
  3. this.beanFactory.getBeanPostProcessorCount() <
    this.beanPostProcessorTargetCount

1和3看起来是没多大发挥空间,我们可以看下2,2的代码块如下

 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;}}

从代码我们可以看出

bd.getRole() == RootBeanDefinition.ROLE_INFRASTRUCTURE

这句话是核心,然而ROLE_INFRASTRUCTURE这个又是什么鬼,我们继续跟踪

 /*** Role hint indicating that a {@code BeanDefinition} is providing an* entirely background role and has no relevance to the end-user. This hint is* used when registering beans that are completely part of the internal workings* of a {@link org.springframework.beans.factory.parsing.ComponentDefinition}.*/int ROLE_INFRASTRUCTURE = 2;

这句话表达的意思是当声明这个角色时,这个bean就不是归属外部用户,而是归属spring内部。换句话说就是这个bean是个官方bean,不是群众bean。总之这个就是一个身份标识,因此我们在把bean注入到spring容器中,就可以做如下处理

    @Bean@Role(RootBeanDefinition.ROLE_INFRASTRUCTURE)public InterceptorHandler interceptorHandler(final ObjectProvider<List<Interceptor>> listObjectProvider) {return new InterceptorHandler(interceptorChain(listObjectProvider));}

当加上

 @Role(RootBeanDefinition.ROLE_INFRASTRUCTURE)

这个注解后,世界果然清净了,控制台再也没有出现

not eligible for getting processed by all BeanPostProcessors

但问题真的就解决了吗?

答案见仁见智,很多时候我们很容易欺骗一个人一时,但却很难欺骗这个人一世,好比如你告诉妹子我家财万贯,妹子相信了,等到妹子要你给她买一些贵重的东西时,发现你买不起,你为了讨妹子欢心,不得以打肿脸充胖子,提前消费你压根买不起的东西,导致你后面没法再消费其他你本可以消费的东西

在spring世界也是如此,BeanPostProcessor本身也是一个Bean,一般而言其实例化时机要早过普通的Bean,但是她现在对于你实现的bean有一些需求,即BeanPostProcessor有时也会依赖一些Bean,这就导致了一些普通Bean的实例化早于BeanPostProcessor的可能情况,而引发一些情况,比如这些提前初始化的bean无法享有一些后置处理器扩展的功能

因此对本文的案例,用

 @Role(RootBeanDefinition.ROLE_INFRASTRUCTURE)

其实是没解决问题本质,但是因为本文的拦截器不需要后续的一些spring特色功能,因此这种解法也算是一种吧。

那有没有其他解法,答案是有的,我们可以利用

org.springframework.beans.factory.SmartInitializingSingleton

这个类,他这个类里面有个

afterSingletonsInstantiated()

方法,这个方法的作用是在所有单例bean初始化完成调用后的回调接口。本文后面的例子就是改用这个接口实现,代码如下

public class SpiInstanceInitializingSingleton implements SmartInitializingSingleton,BeanFactoryAware {private DefaultListableBeanFactory beanFactory;private InterceptorHandler interceptorHandler;public SpiInstanceInitializingSingleton(InterceptorHandler interceptorHandler) {this.interceptorHandler = interceptorHandler;}@Overridepublic void afterSingletonsInstantiated() {changeBeanInstance2ProxyInstance();}}

当然还可以使用spring的监听机制,比如监听refresh事件进行处理

总结

本文算是自定义实现的SPI如何与spring进行整合这篇文章的一点扩展补充

demo链接

https://github.com/lyb-geek/springboot-learning/tree/master/springboot-spi-enhance/springboot-spi-framework-spring

排查not eligible for getting processed by all BeanPostProcessors相关推荐

  1. is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for

    springboot项目创建常见问题(持续更新!) https://blog.csdn.net/libusi001/article/details/97267365 Bean 'org.springf ...

  2. is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-

    springboot项目创建常见问题(持续更新!) springboot项目创建常见问题(建议收藏!!!) 目录 一.报错信息 二.信息解析 三.解决方法 四.其他解决方案 一.报错信息 Bean ' ...

  3. springboot+shiro is not eligible for getting processed by all BeanPostProcessors

    项目背景: 服务基于springboot搭建,shiro做认证鉴权,本地启动正常,打包正常,服务器启动正常,采用jenkins打包部署服务,偶尔出现问题 原因分析: 因为问题是偶现的,当时觉得是环境问 ...

  4. SpringBoot项目启动失败: is not eligible for getting processed by all BeanPostProcessors (for example: not)

    SpringBoot项目启动失败报错: ConfigurationPropertiesRebinderAutoConfiguration$$EnhancerBySpringCGLIB$$f4a94db ...

  5. 提示BeanPostProcessorChecker:is not eligible for getting processed by all BeanPostProcessors的原因

    今天有读者朋友反馈在调试本书15章的源码时出现"BeanPostProcessorChecker:xxx is not eligible for getting processed by a ...

  6. is not eligible for getting processed by all BeanPostProcessors 导致找不到路径报404

    今天复制一个相同的项目,在这个项目的基础上重新修改后, 启动一切正常: 但是用postman连接时,一直报404: 在打开其他项目尝试连接后,发现并不是server配置的问题,然后我仔细看日志,发现: ...

  7. 解决:is not eligible for getting processed by all BeanPostProcessors

    文章目录 问题描述 分析 总结 解决 方案1:延迟初始化 方案2:@Role(BeanDefinition.ROLE_INFRASTRUCTURE) 参考 问题描述 SpringBoot项目整合Shi ...

  8. Shiro--解决is not eligible for getting processed by all BeanPostProcessors

    原文网址:Shiro--解决is not eligible for getting processed by all BeanPostProcessors_IT利刃出鞘的博客-CSDN博客 简介 说明 ...

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

    标题上打印的日志是info级别的,不影响程序正常使用,但是有代码洁癖的我还是看着不爽,总想找出问题所在,查了很久知道了是IOC容器注册Bean的时候使用到了还未注册到IOC容器中的Bean,也就是某一 ...

最新文章

  1. 加密解密php,PHP实现的加密解密处理类
  2. 终于要揭开神秘面纱?Magic Leap将要展示产品
  3. python包导入方式_python导包的几种方法(自定义包的生成以及导入详解)
  4. [翻译] 使用 Serverless 和 .NET Core 构建飞速发展的架构
  5. Link-State协议的PRC计算详解
  6. 苹果笔记本调整 pycharm 字体大小的地方
  7. openstack实例启动失败_Nokia NESC,这是世界上最大的OpenStack私有云之一
  8. 机器学习资料合计(一)
  9. java多表查询实体类_自己设计一个JAVA+MyBatis解析实体类多表通用查询
  10. 用python实现传染病模型传染病模型
  11. 论文查重会查新闻内容吗?
  12. IPTV直播系统用P2P直播加速能节省带宽吗?
  13. poj1564 Sum it up
  14. Microsoft Edge逃离360之路
  15. OpenGL深入探索——阴影贴图(二)
  16. Java开发环境基础配置
  17. 3. MySQL之PyMySQL的安装使用
  18. 头歌--C++之if-else基本性质
  19. arduino笔记15:按键开关输入
  20. trunk端口配置错误导致环路

热门文章

  1. oracle死锁进程杀不掉,oracle杀死死锁进程
  2. 新西兰做java_新西兰华人的真实生活,真是吓到我了
  3. Studio5000 V33初学(一):FAL指令
  4. 广东计算机专业软件排名前十大学,2017年全国计算机专业大学排名一览表
  5. 基于STC8的红外遥控灯
  6. ElasticSearch实现商品搜索与聚合分析
  7. 掌握并理解 CORS (跨域资源共享)
  8. 家用工具套装_一套适合家用的简洁便携工具箱(WORKPOR)
  9. 您需要了解的OOP(S)概念
  10. 为树莓派打实时preempt_rt补丁