Spring @Primary Annotation – Spring @Primary Annotation

最后修改: 2018年 7月 26日

中文/混合/英文(键盘快捷键:t)

 

1. Overview

1.概述

In this quick tutorial, we’ll discuss Spring’s @Primary annotation which was introduced with version 3.0 of the framework.

在这个快速教程中,我们将讨论Spring的@Primary注解,它是在框架的3.0版本中引入的。

Simply put, we use @Primary to give higher preference to a bean when there are multiple beans of the same type.

简单地说,我们使用@Primary来在有多个相同类型的Bean时给予一个Bean更高的优先权。

Let’s describe the problem in detail.

让我们详细描述一下这个问题。

2. Why Is @Primary Needed?

2.为什么需要@Primary

In some cases, we need to register more than one bean of the same type.

在某些情况下,我们需要注册一个以上的相同类型的Bean

In this example we have JohnEmployee() and TonyEmployee() beans of the Employee type:

在这个例子中,我们有JohnEmployee()TonyEmployee()Bean的Employee类型。

@Configuration
public class Config {

    @Bean
    public Employee JohnEmployee() {
        return new Employee("John");
    }

    @Bean
    public Employee TonyEmployee() {
        return new Employee("Tony");
    }
}

Spring throws NoUniqueBeanDefinitionException if we try to run the application.

如果我们试图运行应用程序,Spring会抛出NoUniqueBeanDefinitionException

To access beans with the same type we usually use @Qualifier(“beanName”) annotation.

为了访问具有相同类型的Bean,我们通常使用@Qualifier(“beanName”)注解。

We apply it at the injection point along with @Autowired. In our case, we select the beans at the configuration phase so @Qualifier can’t be applied here. We can learn more about @Qualifier annotation by following the link.

我们在注入点与@Autowired一起应用它。在我们的案例中,我们在配置阶段选择了Bean,所以@Qualifier不能在这里应用。我们可以通过关注链接来了解更多关于@Qualifier注解的信息。

To resolve this issue Spring offers the @Primary annotation.

为了解决这个问题,Spring提供了@Primary注解。

3. Use @Primary With @Bean

3.使用@Primary@Bean

Let’s have a look at configuration class:

让我们看一下配置类。

@Configuration
public class Config {

    @Bean
    public Employee JohnEmployee() {
        return new Employee("John");
    }

    @Bean
    @Primary
    public Employee TonyEmployee() {
        return new Employee("Tony");
    }
}

We mark TonyEmployee() bean with @Primary. Spring will inject TonyEmployee() bean preferentially over the JohnEmployee().

我们将TonyEmployee() Bean标记为@Primary。Spring将优先注入TonyEmployee() Bean而不是JohnEmployee()

Now, let’s start the application context and get the Employee bean from it:

现在,让我们启动应用程序上下文并从中获取Employee Bean。

AnnotationConfigApplicationContext context
  = new AnnotationConfigApplicationContext(Config.class);

Employee employee = context.getBean(Employee.class);
System.out.println(employee);

After we run the application:

在我们运行应用程序后。

Employee{name='Tony'}

From the output, we can see that the TonyEmployee() instance has a preference while autowiring.

从输出中,我们可以看到TonyEmployee() 实例在自动布线时有一个偏好

4. Use @Primary With @Component

4.使用@Primary@Component

We can use @Primary directly on the beans. Let’s have a look at the following scenario:

我们可以直接在bean上使用@Primary。让我们看一下下面的情况。

public interface Manager {
    String getManagerName();
}

We have a Manager interface and two subclass beans, DepartmentManager:

我们有一个Manager接口和两个子类bean,DepartmentManager

@Component
public class DepartmentManager implements Manager {
    @Override
    public String getManagerName() {
        return "Department manager";
    }
}

And the GeneralManager bean:

还有GeneralManagerbean。

@Component
@Primary
public class GeneralManager implements Manager {
    @Override
    public String getManagerName() {
        return "General manager";
    }
}

They both override the getManagerName() of the Manager interface. Also, note that we mark the GeneralManager bean with @Primary.

它们都覆盖了Manager接口的getManagerName()。另外,请注意,我们用@Primary来标记GeneralManagerbean。

This time, @Primary only makes sense when we enable the component scan:

这一次,@Primary只有在我们启用组件扫描时才有意义

@Configuration
@ComponentScan(basePackages="org.baeldung.primary")
public class Config {
}

Let’s create a service to use dependency injection while finding the right bean:

让我们创建一个服务来使用依赖性注入,同时寻找合适的bean。

@Service
public class ManagerService {

    @Autowired
    private Manager manager;

    public Manager getManager() {
        return manager;
    }
}

Here, both beans DepartmentManager and GeneralManager are eligible for autowiring.

在这里,BeanDepartmentManagerGeneralManager都有资格进行自动布线。

As we marked GeneralManager bean with @Primary, it will be selected for dependency injection:

由于我们将GeneralManagerbean标记为@Primary,它将被选中进行依赖注入

ManagerService service = context.getBean(ManagerService.class);
Manager manager = service.getManager();
System.out.println(manager.getManagerName());

The output is “General manager”.

输出结果是”总经理”.

5. Conclusion

5.结论

In this article, we learned about Spring’s @Primary annotation. With the code examples, we demonstrated the need and the use cases of the @Primary.

在这篇文章中,我们了解了Spring的@Primary注解。通过代码示例,我们展示了@Primary.的必要性和使用情况。

As usual, the complete code for this article is available over on GitHub project.

像往常一样,本文的完整代码可在GitHub项目上获得over