springboot Bean提前加载未被BeanPostProcessor增强处理导致aop注解切面失效及解决办法

  • 时间:2025-10-27 22:49 作者: 来源: 阅读:4
  • 扫一扫,手机访问
摘要:前言 最近碰到个问题,公司项目中使用了shiro权限框架并自定义了UserRealm类,目前我要在其中注入一个Service类,调用运行一个业务逻辑,而这个方法上带有aop注解切面。结果,这整个Service类内的所有方法上带有的切面都失效了,就很牛逼,其他Service内同个注解的切面则正常。 探索过程 然后我注意到在控制台上有条关于UserRealm类的

前言

最近碰到个问题,公司项目中使用了shiro权限框架并自定义了UserRealm类,目前我要在其中注入一个Service类,调用运行一个业务逻辑,而这个方法上带有aop注解切面。结果,这整个Service类内的所有方法上带有的切面都失效了,就很牛逼,其他Service内同个注解的切面则正常。

探索过程

然后我注意到在控制台上有条关于UserRealm类的info日志,如下:

2020-11-20 17:09:59.856  INFO 11872 --- [           main] trationDelegate$BeanPostProcessorChecker : Bean  userRealm  of type [xxx.shiro.UserRealm] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)

翻译结果是:

类型为[xxx.shiro.UserRealm]的Bean userRealm 不符合所有BeanPostProcessor的处理要求(例如:不符合自动代理的条件)

而且基本都是shiro模块相关的类输出的,之前没了解过BeanPostProcessor类,但大致意思可以理解,代理未生效。

切面失效缘由及BeanPostProcessor(后置处理器)类作用

BeanPostProcessor本身也是一个Bean,一般而言实则例化时机要早过普通的Bean。
百度后我清楚了,是由于UserRealm在BeanPostProcessor之前加载了,没有被增强处理过导致的。

执行过程

从Application运行开始 -> ServletWebServerApplicationContext类的refresh() -> 父类AbstractApplicationContext的refresh() -> registerBeanPostProcessors() -> PostProcessorRegistrationDelegate类的静态registerBeanPostProcessors()

public static void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {
    // 注意:此处只会拿到Bean的定义信息~~~~
    // 已经被实例化的Bean最终都会调用`beanFactory.addBeanPostProcessor`而缓存在AbstractBeanFactory的字段:beanPostProcessors里,它是个CopyOnWriteArrayList
    // 更重大的是:最终最终所有的BeanPostProcessor的执行都会从这个List里面拿出来执行
    // 所以这一步很关键:那就是按照顺序,把`BeanPostProcessor`们都实例化好,然后添加进List里
    // 因此顺序是关键~~~~~如果某些Bean提前被实例化,它就很有可能不能被所有的`BeanPostProcessor`处理到了
    // 这也是我们BeanPostProcessorChecker的作用,它就是检查这个然后输出日志的~
    String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);

    // 这个beanProcessorTargetCount此处赋值了,后续就都不会变了,BeanPostProcessorChecker就是和这个进行比较的~
    // beanFactory里面的Bean实例总个数+1(自己)+bean定义信息~
    int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;
    // 把BeanPostProcessorChecker加进去,它实则就是做了一个检查而已~~~~~~~输出一个info日志~
    beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));

    // 1、找到所有实现PriorityOrdered的`BeanPostProcessor`,然后getBean,然后统一排序,然后beanFactory.addBeanPostProcessor()
    // 2、处理实现Ordered的,步骤同上
    // 3、处理没实现排序接口的普通的处理器,不需要sort了,直接add进去~

    // 最后注册一个特殊的处理器
    beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));
}




springboot Bean提前加载未被BeanPostProcessor增强处理导致aop注解切面失效及解决办法

其中,Bean被提前加载的info日志就是由BeanPostProcessorChecker类输出的。





springboot Bean提前加载未被BeanPostProcessor增强处理导致aop注解切面失效及解决办法


这是最后添加完毕的BeanPostProcessor类数组。





springboot Bean提前加载未被BeanPostProcessor增强处理导致aop注解切面失效及解决办法


postProcessorNames数组里的就是早于BeanPostProcessor加载的类,UserRealm附带于红框内的Bean。

解决方案

shiro模块的Bean被提前加载是无法解决的,只能延迟其中注入的Service加载时间。

@Autowired
@Lazy
private TestService testService;

如上,附上Spring的@Lazy注解就行了,或者使用@Autowired的required = "false",然后在调用处主动校验并从上下文获取Service实例。很明显用@Lazy方便多了。

参考链接

【小家Spring】注意BeanPostProcessor启动时对依赖Bean的“误伤”陷阱(is not eligible for getting processed by all...)

  • 全部评论(0)
最新发布的资讯信息
【系统环境|】在Qt中如何设置窗体的背景图片(2025-10-29 20:27)
【系统环境|】无声无名 | 杨·罗威斯终身回顾展(2025-10-29 20:26)
【系统环境|】从零开始学Qt(22):QSS详解(3)- 盒子模型(2025-10-29 20:25)
【系统环境|】Quarkus vs Spring Boot 集成 RabbitMQ 谁更香?(2025-10-29 20:24)
【系统环境|】RabbitMQ相关概念及代码示例(2025-10-29 20:24)
【系统环境|】Spring Boot + RabbitMQ:轻松掌握五种基本工作模式(2025-10-29 20:23)
【系统环境|】一篇文章带你彻底玩转-RabbitMQ(2025-10-29 20:22)
【系统环境|】私有云平台搭建——史上最详细(2025-10-29 20:21)
【系统环境|】RabbitMQ最全详解(万字图文总结)(2025-10-29 20:20)
【系统环境|】.Net/C#全网最火RabbitMQ操作【强烈推荐】(2025-10-29 20:20)
手机二维码手机访问领取大礼包
返回顶部