简体   繁体   English

使用@Qualifier 指定的 bean 注入点时,如何扩展命名的 Spring bean?

[英]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 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?这个怎么运作?

  • Spring will try to load a bean named "bean1". Spring 将尝试加载名为“bean1”的 bean。 If it doesn't find any bean by the same name that is marked as @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.有多种选择。

Override bean definition with @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

Create custom @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.

相关问题 如何在spring中通过默认的限定符bean名称获取@Service bean - how do i get @Service bean by its default qualifier bean name in spring Spring 中使用 @Bean 和 @Qualifier 注释的 Bean 名称解析 - Bean name resolution in Spring using @Bean and @Qualifier annotations Spring 3.1:具有多个@Qualifier引用指向相同的Bean ID - Spring 3.1: Have Multiple @Qualifier References Point to Same Bean ID 如何定义具有限定符的特定 bean,该限定符将为其依赖项指定特定 bean? - How do I define a specific bean with a qualifier that would designate a specific bean for its dependancies? 在Spring MVC中,使用会话范围的bean完成操作后,是否需要解除绑定到该会话的bean对象的绑定? 如果是,怎么办? - In Spring MVC, do I need to unbind bean objects bound to the session when I am done using the session scoped bean? If yes, how? Spring @Bean 名称,不适用于 @Qualifier - Spring @Bean Name, is not working with @Qualifier 没有豆有资格注射到注射点 - No bean is eligible for injection to the injection point 如何使用Spring创建HashMap bean - How do I create a HashMap bean using Spring 使用 Spring Web 流程 1 时,如何将 object 添加到 bean 中的列表? - When using Spring Web Flow 1, how do I add an object to a list in a bean? 春豆田注射 - Spring bean fields injection
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM