You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Prototype作用域创建Spring DataSource遇依赖问题求助

问题:Prototype作用域Spring Bean启动时依赖缺失异常

场景与配置

尝试创建Prototype作用域的DriverManagerDataSource Bean,数据库连接信息在运行时传入,相关配置代码如下:

配置类代码

@Configuration
class Cfg {
    @Bean
    public Function<DataSourcePropertiesMap, DriverManagerDataSource> functionOfDriverMgrDS() {
        return this::driverManagerDataSource;
    }

    @Lazy
    @Bean
    @Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE)
    public DriverManagerDataSource driverManagerDataSource(DataSourcePropertiesMap dbPropsMap) {
        var ds = new DriverManagerDataSource(dbPropsMap.getDbURL(), dbPropsMap.getDbUsername(), dbPropsMap.getDbPassword());
        ds.setDriverClassName(dbPropsMap.getDbDriver());
        return ds;
    }
}

参数容器类代码

@Getter
@AllArgsConstructor
public class DataSourcePropertiesMap {

    @NonNull private final String dbURL;
    @NonNull private final String dbUsername;
    @NonNull private final String dbPassword;
    @NonNull private final String dbDriver;
}

启动异常

应用启动时抛出依赖缺失异常:

Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'healthContributorRegistry' defined in class path resource [org/springframework/boot/actuate/autoconfigure/health/HealthEndpointConfiguration.class]: Unsatisfied dependency expressed through method 'healthContributorRegistry' parameter 2; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'dbHealthContributor' defined in class path resource [org/springframework/boot/actuate/autoconfigure/jdbc/DataSourceHealthContributorAutoConfiguration.class]: Unsatisfied dependency expressed through method 'dbHealthContributor' parameter 0; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'driverManagerDataSource' defined in class path resource [Cfg.class]: Unsatisfied dependency expressed through method 'driverManagerDataSource' parameter 0; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'DataSourcePropertiesMap' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}

疑问

原本认为Prototype作用域的Bean会在调用时传入参数创建新实例,为何Spring仍要求存在DataSourcePropertiesMap类型的Bean?若配置该类的默认Bean,还会要求提供有效的驱动类。


原因分析与解决方案

原因

问题出在Spring Boot Actuator的自动配置:DataSourceHealthContributorAutoConfiguration会自动探测容器中所有的DataSource Bean,在应用启动时尝试初始化实例以进行健康检查。即使是Prototype作用域的Bean,Actuator触发创建时,Spring会尝试从容器中查找driverManagerDataSource方法的依赖DataSourcePropertiesMap,但该类并未注册为Spring Bean,因此抛出缺失依赖的异常。

而Prototype Bean的参数传入逻辑仅在主动调用ApplicationContext.getBean(Class, Object...)或通过Function手动创建时生效,容器自动触发的Bean创建(如Actuator自动装配)会遵循常规的依赖注入规则,从容器中查找依赖。

解决方案

方案1:排除DataSource健康检查自动配置

在启动类上添加注解,排除Actuator的数据源健康检查配置,避免其自动初始化DataSource Bean:

@SpringBootApplication
@EnableAutoConfiguration(exclude = DataSourceHealthContributorAutoConfiguration.class)
public class YourApplication {
    public static void main(String[] args) {
        SpringApplication.run(YourApplication.class, args);
    }
}

方案2:不将DataSource注册为Spring Bean,通过Function完全控制创建

修改配置类,去掉driverManagerDataSource方法上的@Bean、@Scope等注解,仅保留创建DataSource的Function Bean,由业务代码手动调用创建实例:

@Configuration
class Cfg {
    @Bean
    public Function<DataSourcePropertiesMap, DriverManagerDataSource> functionOfDriverMgrDS() {
        return this::driverManagerDataSource;
    }

    // 普通方法,不注册为Spring Bean
    private DriverManagerDataSource driverManagerDataSource(DataSourcePropertiesMap dbPropsMap) {
        var ds = new DriverManagerDataSource(dbPropsMap.getDbURL(), dbPropsMap.getDbUsername(), dbPropsMap.getDbPassword());
        ds.setDriverClassName(dbPropsMap.getDbDriver());
        return ds;
    }
}

业务代码中注入Function并创建数据源:

@Service
public class DataSourceService {
    private final Function<DataSourcePropertiesMap, DriverManagerDataSource> dsCreator;

    public DataSourceService(Function<DataSourcePropertiesMap, DriverManagerDataSource> dsCreator) {
        this.dsCreator = dsCreator;
    }

    public DriverManagerDataSource createRuntimeDataSource(String url, String username, String password, String driver) {
        DataSourcePropertiesMap props = new DataSourcePropertiesMap(url, username, password, driver);
        return dsCreator.apply(props);
    }
}

方案3:禁用特定数据源的健康检查

如果需要保留DataSource作为Spring管理的Prototype Bean,可在配置文件中禁用Actuator的数据库健康检查:

# 禁用所有数据库健康检查
management.health.db.enabled=false

或者通过自定义健康指示器,仅检查特定数据源,避免触发目标Prototype Bean的初始化。


内容的提问来源于stack exchange,提问作者Kryptix

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 01:55:21