Spring Boot中DataSource未触发BeanPostProcessor的postProcessAfterInitialization问题
1. 初始化顺序问题(最高概率)
当前DatasourceProxyBeanPostProcessor中@Autowired注入了大量普通业务Bean(AmqpTemplate/MetricsEndpoint等),这些Bean的初始化过程大概率依赖DataSource,导致Spring容器先初始化DataSource,再初始化该BeanPostProcessor,等BeanPostProcessor初始化完成后已经错过DataSource的处理时机,自然不会触发判断逻辑。
解决方案
给所有注入的依赖添加@Lazy注解,让这些依赖在实际使用时才初始化,避免阻塞BeanPostProcessor的实例化:
@Autowired @Lazy private AmqpTemplate amqpTemplate; @Autowired @Lazy private Clock clock; // 其余所有@Autowired标注的依赖都统一添加@Lazy注解
同时将类上的@Configuration改为@Component,@Configuration本身是用于注册Bean的配置类,作为BeanPostProcessor的载体使用@Component更符合Spring规范,也能避免部分场景下的优先级异常。
2. 配置条件未生效
类上标注了@ConditionalOnProperty(value="enable.dbmonitor", havingValue="true", matchIfMissing= false),如果配置文件中没有显式配置enable.dbmonitor=true,这个类根本不会被Spring容器注册,自然不会执行任何逻辑。
解决方案
在properties配置文件中添加配置项:
enable.dbmonitor=true
3. 数据源被提前代理导致类型判断失效
如果项目中集成了Druid、MyBatis-Plus、动态数据源等组件,DataSource在被该BeanPostProcessor处理前已经被代理为JDK动态代理/CGLIB代理类,直接使用instanceof判断可能失效(常见于JDK代理未显式暴露DataSource接口的场景)。
解决方案
使用Spring提供的Aop工具类判断真实类型,修改判断逻辑:
// 先导入工具类 import org.springframework.aop.support.AopUtils; @Override public Object postProcessAfterInitialization(final Object bean, final String beanName) { Class<?> targetClass = AopUtils.getTargetClass(bean); if (DataSource.class.isAssignableFrom(targetClass) && !ProxyDataSource.class.isAssignableFrom(targetClass)) { // 原有代理逻辑 } return bean; }
4. 代理返回逻辑写反
现有代码的代理返回逻辑完全错误,即使判断条件触发,也会返回原数据源而非代理对象:
// 错误逻辑:代理生成成功反而返回原对象 return factory.getProxy() == null ? factory.getProxy() : bean;
解决方案
修改为正确逻辑:
Object proxy = factory.getProxy(); return proxy != null ? proxy : bean;
排查小技巧
代码中已经添加了打印逻辑:
System.out.println(beanName+" : "+bean.getClass().toString()); System.out.println((bean instanceof DataSource));
启动项目后直接搜索控制台中dataSource对应的打印行,查看该Bean的实际类型、以及instanceof的输出结果,可快速定位是未走到处理逻辑,还是类型判断不通过。
内容的提问来源于stack exchange,提问作者yosra skah

