我有一个配置类,它根据选定的概要文件定义了两个bean,其中包含重写的配置方法:
@Configuration
class MyConfig {
@Profile("profile")
@Bean
MyBean myBean(MyBeanProperties properties) {
return new MyBean(properties);
}
@Profile("!profile")
@Bean
MyBean myBean(MyBeanProperties properties, AdditionalProperties addProps) {
MyBean result = new MyBean(properties);
result.addAdditionalProperties(addProps);
return result;
}
}
和一个将MyBean
自动连接到其中的类
@Service
class MyService {
MyBean autowiredBean;
private MyService(MyBean bean) { this.autowiredBean = bean; }
}
现在,当我启动Spring上下文时,它失败并显示消息
com.example.MyServce中的构造函数的参数0需要一个类型为'com.example.MyBean'的bean。
那怎么可能?我清楚地定义了Spring bean,以便在创建上下文时将其显示。
答案 0 :(得分:1)
这是由于两个 bean 定义了相同的方法名称,并且根据某些条件(在这种情况下基于配置文件)预计将跳过其中一个 bean 时引起的。在这种情况下,“myBean”用不同的配置文件定义了两次。
解析配置类的方式是遍历该类中的所有 beanMethods 并添加相应的 bean 定义。迭代是按照 beanMethods 在 config 类中定义的顺序进行的。 Here 是代码的链接。
根据这些 bean 在 config 类中定义的顺序,如果根据配置文件注释预期跳过定义的第一个 bean,则 beanMethod 名称将添加到“to-be-skiipped”列表中豆方法。 Here 是代码的链接。
现在,当它遇到同名的第二个 bean 时,它看到这个 beanMethod 名称已经存在于“要跳过的”方法列表中,因此即使没有固有条件(例如配置文件),这将导致它被跳过。 Here 是代码的链接。
您会注意到,如果您交换 bean 的顺序并使用之前失败的相同配置文件来运行,那么 bean 将被拾取。
在配置类中使用唯一的 beanMethod 名称将是避免这种情况的最佳方法。
答案 1 :(得分:0)
这样做的原因是,由于配置方法的名称,Spring认为这些Bean具有相同的名称,因此它无法实例化它们(尽管在任何给定的活动Profile中仅应创建一个)。可以正常工作:
@Configuration
class MyConfig {
@Profile("profile")
@Bean
MyBean myBean(MyBeanProperties properties) {
return new MyBean(properties);
}
@Profile("!profile")
@Bean
// note different method name
MyBean otherBean(MyBeanProperties properties, AdditionalProperties addProps) {
MyBean result = new MyBean(properties);
result.addAdditionalProperties(addProps);
return result;
}
}
我在任何地方都没有找到这种行为的解释,所以我发布了这个自我回答的问题以供分享。
在我的现实生活中,发生了WebClient
实例化,该实例在一个配置文件中用一个客户注册实例化,而在另一个配置文件中却没有一个(因为创建交换过滤器不需要)。 >
答案 2 :(得分:0)
我发现了为什么更改方法名称允许应用程序上下文加载:
问题是,spring容器要求所有的bean都具有此处https://docs.spring.io/spring/docs/current/spring-framework-reference/core.html#beans-beanname所描述的唯一名称
每个bean具有一个或多个标识符。这些标识符在承载Bean的容器内必须是唯一的。
当不使用XML配置时,我认为具有相同bean方法名称的唯一方法是为@Bean(NAME)
批注中的bean提供唯一的名称,有关详细信息,Spring bean with same method name but different qualifier fail to load