简体   繁体   English

当我们可以为 bean 命名时,为什么还要使用限定符?

[英]Why do we use a qualifier when we can have a name for the bean?

Why do we use qualifiers with @Bean when we can have different names for different beans of the same type (class)?当我们可以为相同类型(类)的不同 bean 使用不同的名称时,为什么我们要对 @Bean 使用限定符?

@Bean
@Qualifier("fooConfig")
public Baz method1() {

}

Isn't the following code more clean?下面的代码不是更干净吗?

@Bean("fooConfig")
public Baz method1() {

}

If I create two beans of the same type with different names (using @Bean annotation), then can we inject them specifically using the @Qualifier annotation(can be added on field/constructor parameter/setter) in another bean?如果我创建两个具有不同名称的相同类型的 bean(使用 @Bean 注释),那么我们可以使用 @Qualifier 注释(可以添加到字段/构造函数参数/setter 上)专门将它们注入另一个 bean 中吗?


@Bean("fooConfig")
public Baz method1(){

}

@Bean("barConfig")
public Baz method2(){

}

// constructor parameter of a different bean
final @Qualifier("fooConfig") Baz myConfig

If the above is true, then where do we use @Qualifier (with @Bean or @Component) instead of giving the bean a name as shown below?如果以上是正确的,那么我们在哪里使用@Qualifier(与@Bean 或@Component)而不是给bean 命名,如下所示?


@Bean
@Qualifier("fooConfig")
public Baz method1(){

}

@Bean
@Qualifier("barConfig")
public Baz method2(){

}

// constructor parameter of a different bean
final @Qualifier("fooConfig") Baz myConfig
  1. Beans have names.豆子有名字。 They don't have qualifiers.他们没有限定词。 @Qualifier is annotation, with which you tell Spring the name of Bean to be injected. @Qualifier 是注解,告诉 Spring 要注入的 Bean 的名称。

  1. No.不。

  1. Default Qualifier is the only implementation of the interface(example is below, 4th question) or the only method with a particular return type.默认限定符是接口的唯一实现(示例如下,第 4 个问题)或唯一具有特定返回类型的方法。 You don't need to specify the @Qualifier in that case.在这种情况下,您不需要指定 @Qualifier。 Spring is smart enough to find itself. Spring 足够聪明,可以找到自己。

For example:例如:

@Configuration
public class MyConfiguration {
    @Bean
    public MyCustomComponent myComponent() {
        return new MyCustomComponent();
    }
}

If you will try to inject myComponent somewhere, Spring is smart enough to find the bean above.如果您将尝试在某处注入 myComponent,Spring 足够聪明,可以找到上面的 bean。 Becaude there is only one Bean with return type MyCustomComponent.因为只有一个返回类型为 MyCustomComponent 的 Bean。 But if there was a couple of methods, that would return MyCustomComponent, then you would have to tell Spring which one to inject with @Qualifier annotation.但是如果有几个方法,它们会返回 MyCustomComponent,那么您将必须告诉 Spring 要用 @Qualifier 注释注入哪个。

SIDENOTE: @Bean annotation by default Spring uses the method name as a bean name.旁注:@Bean 注解默认 Spring 使用方法名作为 bean 名。 You can also assign other name like @Bean("otherComponent").您还可以分配其他名称,如@Bean("otherComponent")。


  1. You have one Interface, and a couple of Classes implementing it.您有一个接口和几个实现它的类。 You inject bean of your interface.您注入接口的 bean。 How can Spring know which Class should be used? Spring怎么知道应该用哪个Class呢?

This is you interface:这是你的界面:

public interface TestRepository{}

This is your implementation 1:这是您的实施 1:

@Repository
public class Test1Repository implements TestRepository{}

Your implementation 2:您的实施 2:

@Repository
public class Test2Repository implements TestRepository{}

Now you are injecting it like:现在你正在注入它:

private final TestRepository testRepository;

public TestServiceImpl(TestRepository testRepository) {
    this.testRepository= testRepository;
}

QUESTION?题? How is Spring supposed to know which class to inject? Spring 应该如何知道要注入哪个 class? Test1 or Test2.测试 1 或测试 2。 That's why you tell it with @Qualifier which class.这就是为什么你用 @Qualifier 告诉它哪个类。

private final TestRepository testRepository;

public TestServiceImpl(@Qualifier("test1Repository") TestRepository testRepository) {
    this.testRepository= testRepository;
}

I Prefer different method to not using @Qualifier我更喜欢not使用 @Qualifier 的不同方法

  1. Create common Interface创建通用接口
public interface CommonFooBar{ public String commonFoo(); public String commonBar(); }
  1. Extends to each service扩展到每项服务
public interface FooService extends CommonFooBar { } public interface BarService extends CommonFooBar { }
  1. Then using it to your class然后将它用于您的 class
 @Autowired FooService fooService; or @Autowired BarService barService;

so, we can defined the single responsibility to each interface and This kind of segregation is more readable to every junior.所以,我们可以为每个接口定义单一的职责,这种分离对每个初级人员来说更具可读性。

I quite like a different way of working.我非常喜欢不同的工作方式。 Surely if you provide a unique name for your bean, then that is all you need?当然,如果您为您的 bean 提供了一个唯一的名称,那么这就是您所需要的了吗?

Given the example below, its easy to see that Spring will name the beans based on the method name used to create the beans.在下面的示例中,很容易看出 Spring 将根据用于创建 bean 的方法名称来命名 bean。 In other words, if you give your beans sensible names, then the code should become self-explanatory.换句话说,如果您给 bean 起合理的名称,那么代码应该是不言自明的。 This also works when injecting beans into other classes.这在将 bean 注入其他类时也有效。

The end result of this is:这样做的最终结果是:

  • Spring will name your beans based on the method used to create them. Spring 将根据用于创建它们的方法命名您的 bean。
  • If you import a bean, Spring will try to match on the bean name.如果导入一个 bean,Spring 将尝试匹配 bean 名称。
  • If you try to import a bean that does not match the name, Spring will attempt to match the class.如果您尝试导入与名称不匹配的 bean,Spring 将尝试匹配 class。
  • If your injected field name does not match the bean name and there are more than one instance of your bean, Spring will throw an exception on startup as it won't know which one to inject.如果您注入的字段名称与 bean 名称不匹配,并且有多个 bean 实例,Spring 将在启动时抛出异常,因为它不知道要注入哪一个。

Lets not over-complicate Spring.让我们不要过于复杂 Spring。

@Bean
mqConnectionFactory() {
    ConnectionFactory connectionFactory = new MQXAConnectionFactory();
    return connectionFactory;
}

@Bean 
public ConnectionFactory pooledConnectionFactory(ConnectionFactory mqconnectionFactory) {
    JmsPoolConnectionFactory connectionFactory = new JmsPoolConnectionFactory();
    connectionFactory.setConnectionFactory(mqConnectionFactory);
    return connectionFactory;
}

@Bean 
public ConnectionFactory cachingConnectionFactory(ConnectionFactory mqConnectionFactory) {
    CachingConnectionFactory connectionFactory = new CachingConnectionFactory();
    connectionFactory.setTargetConnectionFactory(mqConnectionFactory);
    return connectionFactory;
} 

@Bean
public JmsTemplate jmsTemplate(ConnectionFactory cachingConnectionFactory) {
    JmsTemplate jmsTemplate = new JmsTemplate();
    jmsTemplate.setConnectionFactory(cachingConnectionFactory);
    return jmsTemplate;
}

@Bean
public DefaultMessageListenerContainer messageListenerContainer(ConnectionFactory pooledConnectionFactory) {
    DefaultMessageListenerContainer container = new DefaultMessageListenerContainer();
    container.setConnectionFactory(pooledConnectionFactory);
    ...
    return container;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 为什么我们必须使用TableModel作为JTable? - Why do we have to use a TableModel for a JTable? 当我们有 OkHttp 时为什么要使用 Retrofit - why use Retrofit when we have OkHttp 为什么在拥有UrlConnection时使用套接字 - why use Sockets when we have UrlConnection 为什么在使用LinkedBlockingQueue时使用ConcurrentLinkedQueue? - Why use ConcurrentLinkedQueue when we have LinkedBlockingQueue? 如果我们可以使用原始类型,为什么在 Java 中使用 generics 时需要扩展? - Why do we need to extend when using generics in Java if we can just use the original type? 春季豆id值可以有$吗? - Can we have $ in spring bean id value? 为什么在Java中实例化新对象时必须两次键入类名称? - Why do we have to type the class name twice when instantiating a new object in Java? 我们可以在没有 bean 注册的情况下使用 @Autowired 吗? - can we use @Autowired without bean registration? 如果我们可以使用@component,bean 工厂有什么用? - What are bean factories for, if we can use @component? 当我们为接口做匿名类时,我们可以在哪里使用我们可以创建匿名类的场景? - Where can we use the scenario where we can create an anonymous class when we do it for an Interface?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM