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

创建原型作用域Bean引发UnsatisfiedDependencyException的解决咨询

Spring原型Bean注入List时的依赖错误问题

问题场景

定义了一个原型作用域的Bean生成方法:

@Bean
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public A createScopedBeans(String s) {
   return new A(s);
}

该方法每次调用会生成新的A实例。同时定义了Manager的Bean:

@Bean
public Manager manager(List<A> list) {
    return new Manager(list);
}

原本期望Spring自动收集所有A类型Bean来创建Manager,但触发了UnsatisfiedDependencyException,完整异常信息如下:

2023-04-19 15:09:31.100 [main] [WARN ] o.s.c.a.AnnotationConfigApplicationContext - 上下文初始化期间遇到异常 - 取消刷新尝试: org.springframework.beans.factory.UnsatisfiedDependencyException: 创建名称为'manager'的Bean时出错,定义在xxx.xxx: 通过方法'manager'的参数0表达的不满足依赖;嵌套异常是org.springframework.beans.factory.UnsatisfiedDependencyException: 创建名称为'createScopedBeans'的Bean时出错,定义在yyy.yyy: 通过方法'createScopedBeans'的参数0表达的不满足依赖;嵌套异常是org.springframework.beans.factory.NoSuchBeanDefinitionException: 没有找到符合条件的java.lang.String类型Bean: 期望至少有1个符合自动装配候选的Bean。依赖注解: {}

错误原因

并非Spring在寻找单例的A Bean,核心问题是:
Spring尝试自动收集所有A类型Bean时,会触发createScopedBeans这个Bean方法的实例化,但该方法需要传入一个String类型参数,而Spring容器中没有对应的String类型Bean可以自动注入。因为Spring的@Bean方法如果带有参数,默认会尝试从容器中自动装配这些参数,此处没有为String参数指定来源,导致依赖缺失。

解决方法

根据不同的使用场景,可选择以下方案:

场景1:手动创建A实例,无需Spring管理

如果A实例是通过业务代码手动传入参数创建,不需要Spring自动维护这些Bean,直接去掉@Bean和@Scope注解,将方法改为普通工厂方法:

// 改为普通方法,不再作为Spring Bean定义
public A createScopedBeans(String s) {
   return new A(s);
}

之后在Manager的Bean定义中手动收集所需的A实例:

@Bean
public Manager manager() {
    List<A> aList = new ArrayList<>();
    aList.add(createScopedBeans("param1"));
    aList.add(createScopedBeans("param2"));
    // 根据需求添加更多实例
    return new Manager(aList);
}

场景2:需要Spring管理多个不同参数的A原型Bean

如果需要Spring自动管理多个带不同String参数的A原型Bean,可通过以下方式实现:

方式一:为每个参数单独定义A Bean

为每个需要的参数值单独定义一个A类型的Bean,Spring会自动收集所有A类型Bean注入到Manager的List中:

@Bean
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public A a1() {
   return new A("param1");
}

@Bean
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public A a2() {
   return new A("param2");
}
// 可添加更多不同参数的A Bean定义

@Bean
public Manager manager(List<A> list) {
    return new Manager(list);
}

方式二:通过@Value指定参数来源(单参数场景)

如果A的String参数是固定值或可通过配置文件获取,给Bean方法的参数添加@Value注解指定参数来源:

@Bean
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public A createScopedBeans(@Value("${custom.a.param:defaultValue}") String s) {
   return new A(s);
}

这种方式仅适用于只需要一种参数的A实例场景,多参数场景优先选择方式一。

场景3:运行时动态创建带参数的A原型Bean

如果Manager需要在运行时动态创建不同参数的A实例,可注入BeanFactory手动获取实例:

@Bean
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public A createScopedBeans(String s) {
   return new A(s);
}

@Bean
public Manager manager(BeanFactory beanFactory) {
    List<A> aList = new ArrayList<>();
    // 手动传入参数获取原型Bean实例
    aList.add(beanFactory.getBean(A.class, "param1"));
    aList.add(beanFactory.getBean(A.class, "param2"));
    return new Manager(aList);
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 12:58:19