Spring Boot 2.6.7下Hikari配置未生效及手动配置时MBean重复注册问题求助与解决记录
一、自动配置未加载Hikari属性的原因及修复
你遇到的自动配置不生效问题,核心原因在于自定义的CustomHikariDatasource不符合Spring Boot数据源自动配置的触发条件。
查看Spring Boot内置的DataSourceConfiguration.Hikari配置类就能找到答案:
@Configuration(proxyBeanMethods = false) @ConditionalOnClass(HikariDataSource.class) @ConditionalOnMissingBean(DataSource.class) @ConditionalOnProperty(name = "spring.datasource.type", havingValue = "com.zaxxer.hikari.HikariDataSource", matchIfMissing = true) static class Hikari {
这个配置类只有当spring.datasource.type是com.zaxxer.hikari.HikariDataSource(或者未指定type)时才会生效。而你配置的是自定义的app.CustomHikariDatasource,所以Spring Boot不会触发这个自动配置类,导致spring.hikari下的配置属性完全没被加载,连接池只能使用默认的10个连接。
如果想要继续使用自动配置方案,有两种修复思路:
- 让
CustomHikariDatasource继承com.zaxxer.hikari.HikariDataSource,这样保持spring.datasource.type指向自定义类的同时,依然能触发Hikari的自动配置逻辑 - 自定义一个数据源配置类,模仿
DataSourceConfiguration.Hikari的逻辑,把条件中的type改成你的自定义类,同时绑定spring.hikari的配置属性
二、禁用自动配置后HikariConfig重复实例化及MBean冲突问题
当你禁用DataSourceAutoConfiguration后,依然出现HikariConfig被实例化两次的情况,大概率是因为Spring Boot还有其他和Hikari相关的自动配置类在生效(比如HikariDataSourceAutoConfiguration),这些类会自动创建HikariConfig实例,加上你手动定义的@Bean,就导致了重复实例化,进而触发MBean注册冲突——两个Hikari实例都想注册同名的MBean。
你通过自定义MBeanExporter排除dataSourceBean的方案很实用,能直接解决MBean冲突问题:
@Bean public MBeanExporter exporter() { MBeanExporter exporter = new MBeanExporter(); exporter.setAutodetect(true); exporter.setExcludedBeans("dataSource"); return exporter; }
如果想要从根源上避免HikariConfig重复实例化,你需要在禁用自动配置时,把相关的Hikari自动配置类也一并排除:
@SpringBootApplication(exclude = { DataSourceAutoConfiguration.class, HikariDataSourceAutoConfiguration.class })
这样就能彻底阻止Spring Boot自动创建Hikari相关的配置类,完全使用你手动定义的Bean。
最终可行方案
结合你的需求(启用MBean+自定义Hikari数据源),你选择的禁用自动配置+手动创建数据源+自定义MBeanExporter的方案是完全可行的,目前已经能正常运行所有功能,这个方案也是最直接适配你自定义数据源场景的。
内容的提问来源于stack exchange,提问作者Mançaux Pierre-Alexandre

