[英]How do I extend a named Spring bean when using a @Qualifier specified bean injection point?
How do I extend a named bean when using a @Qualifier
specified bean injection point?使用
@Qualifier
指定的 bean 注入点时如何扩展命名 bean?
I have project 1 consisting of 3 spring beans:我的项目 1 由 3 个春豆组成:
@Component("bean1")
public class Bean1 implements Bean {
}
@Component("bean2")
public class Bean2 implements Bean {
}
@Component("bean3")
public class Bean3 {
private Bean bean;
public void setBean(@Qualifier("bean1") final Bean bean) {
this.bean = bean;
}
}
This project is bundled into a jar and included as a dependency on my 2nd project:这个项目被捆绑到一个 jar 中,并作为我的第二个项目的依赖项包含在内:
@Component("bean1")
@Primary
public class Bean1Child extends Bean1 {
}
What I want to happen is for the bean, Bean1Child
, to be injected into Bean3
's setter method.我想要发生的是将 bean
Bean1Child
注入到Bean3
的 setter 方法中。 Unfortunatly I am receiving an error.不幸的是,我收到一个错误。
org.springframework.context.annotation.ConflictingBeanDefinitionException: Annotation-specified bean name 'bean1' for bean class [Bean1Child] conflicts with existing, non-compatible bean definition of same name and class [Bean1]
org.springframework.context.annotation.ConflictingBeanDefinitionException:bean 类 [Bean1Child] 的注释指定的 bean 名称“bean1”与相同名称和类 [Bean1] 的现有的、不兼容的 bean 定义冲突
I needed to use @Qualifier
so that Bean2
is not injected into Bean3
Using the @Primary
annotation did not help.我需要使用
@Qualifier
以便Bean2
不会注入到Bean3
使用@Primary
注释没有帮助。 How can I have Bean1Child
injected into Bean3
when running from my 2nd project?从我的第二个项目运行时,如何将
Bean1Child
注入到Bean3
?
If this is possible, you can change the way the beans are created by removing the @Component
annotations:如果可能,您可以通过删除
@Component
注释来更改创建 bean 的方式:
In the first project, the BeanChild3
would be refactored to get the bean
in the constructor在第一个项目中,
BeanChild3
将被重构以在构造函数中获取bean
public class Bean3 {
private final Bean bean;
public Bean3(final Bean bean) {
this.bean = bean;
}
}
Then we can create the beans in a BeansConfig
class然后我们可以在
BeansConfig
类中创建 bean
@Configuration
class BeansConfig {
@ConditionalOnMissingBean
@Bean("bean1")
Bean bean1(){
return new Bean1();
}
@Bean("bean2")
Bean bean2(){
return new Bean2();
}
@Bean("bean3")
Bean bean3(@Autowired @Qualifier("bean1") Bean){
return new Bean3(bean);
}
}
The @ConditionalOnMissingBean
allows us to provide another bean with the same name to be used instead. @ConditionalOnMissingBean
允许我们提供另一个具有相同名称的 bean 来代替。 If no such bean exists, then the default one would be used.如果不存在这样的 bean,则将使用默认的 bean。
You will then need to create a beanChild1
bean in your second project and it should be picked up.然后你需要在你的第二个项目中创建一个
beanChild1
bean,它应该被选中。
@Bean("bean1")
Bean bean1(){
return new Bean1Child();
}
You can easily achieve this using @ConditionalOnMissingBean
feature.您可以使用
@ConditionalOnMissingBean
功能轻松实现这@ConditionalOnMissingBean
。
Modify your Bean1
class as below修改你的
Bean1
类如下
@Component("bean1")
@ConditionalOnMissingBean(type = "bean1")
public class Bean1 implements Bean {
}
modify Bean1Child
class as below修改
Bean1Child
类如下
@Component
@Qualifier("bean1")
@Primary
public class Bean1Child extends Bean1 {
}
How it works?这个怎么运作?
@Primary
it will fall back to Bean1
class and load it as "bean1".@Primary
的同名 bean,它将回Bean1
类并将其加载为“bean1”。Bean1Child
has to be marked as primary because spring is going to find 2 beans by the same name. Bean1Child
必须被标记为primary,因为spring 将找到2 个同名的bean。 We need to tell which to load.You have multiple beans of the same type and want to prevent Bean2
from injecting.您有多个相同类型的 bean,并希望防止
Bean2
注入。 In some project inject Bean1
and in others Bean1Child
.在一些项目中注入
Bean1
,在其他项目中注入Bean1Child
。
There are multiple options.有多种选择。
@Bean
@Bean
覆盖 bean 定义Make Bean1Child
bean definition the same as Bean1
has using @Bean
使用
@Bean
使Bean1Child
bean 定义与Bean1
相同
@Configuration
public class Config {
@Primary
@Bean
public Bean1 bean1() { //return type must be Bean1
return new Bean1Child();
}
}
and set the property spring.main.allow-bean-definition-overriding=true
并设置属性
spring.main.allow-bean-definition-overriding=true
@Qualifier
annotation@Qualifier
注释@Qualifier
@Target({ElementType.FIELD, ElementType.PARAMETER, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@interface BeanType {
}
@BeanType
public @interface Bean1Type {
}
@Bean1Type
@Component("bean1")
public class Bean1 implements Bean {
}
@Component("bean2")
public class Bean2 implements Bean {
}
@Component("bean3")
public class Bean3 {
private final Bean bean;
public Bean3(@Bean1Type Bean bean) {
this.bean = bean;
}
}
@Bean1Type
@Primary
@Component("bean1Child")
public class Bean1Child extends Bean1 {
}
You cannot have two beans specified with the same qualified name, as the error indicates:不能使用相同的限定名称指定两个 bean,如错误所示:
Annotation-specified bean name 'bean1' for bean class [Bean1Child]
conflicts with existing, non-compatible bean definition of same name and class [Bean1]
Giving a different qualifier name to Bean1Child should work.为 Bean1Child 提供不同的限定符名称应该可以工作。
@Component("bean1child")
@Primary
public class Bean1Child extends Bean1 {
}
and in Bean3 , public void setBean(@Qualifier("bean1child") final Bean bean) {
在 Bean3 中,
public void setBean(@Qualifier("bean1child") final Bean bean) {
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.