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.
在这里,BeanDepartmentManager和GeneralManager都有资格进行自动布线。
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。