SpringPrimary注解
# 1 @Primary注解
@Primary
注解是 Spring 框架中的一个注解,它用于标识一个 bean 是首选的,当容器中存在多个相同类型的 bean 时,Spring 会优先选择使用@Primary
标记的 bean。
以下是 @Primary
注解的一些详细说明:
- 解决依赖注入歧义性: 当你在 Spring 容器中有多个同一类型的 bean,且不确定应该注入哪一个时,使用
@Primary
可以解决这种歧义性。Spring 容器将优先选择标记为@Primary
的 bean 进行注入。 - 适用于构造函数注入、Setter 方法注入、字段注入等:
@Primary
可以用于不同的依赖注入方式,包括构造函数注入、Setter 方法注入以及字段注入。 - 与
@Qualifier
一起使用: 如果在容器中有多个相同类型的 bean,而你仍需要选择性地注入非首选的 bean,你可以结合使用@Primary
和@Qualifier
注解。@Qualifier
允许你指定要注入哪个具体的 bean。 - 适用于多个配置文件: 如果你的应用有多个配置文件,每个配置文件定义了相同类型的 bean,你可以在不同的配置文件中使用
@Primary
标记不同的 bean,以确定哪个是首选的。 - 不是强制性的: 使用
@Primary
是可选的,如果没有标记任何 bean 为首选,Spring 将会抛出 NoUniqueBeanDefinitionException 异常,表示依赖注入存在歧义。
以下是一个示例,说明如何在 Spring 中使用 @Primary
注解:
@Component
@Primary
public class MyPrimaryBean implements MyInterface {
// ...
}
@Component
public class MySecondaryBean implements MyInterface {
// ...
}
@Service
public class MyService {
private MyInterface myInterface;
@Autowired
public MyService(MyInterface myInterface) {
this.myInterface = myInterface;
}
// ...
}
在这个示例中,MyPrimaryBean
被标记为首选 bean,所以当 MyService
类注入 MyInterface
时,MyPrimaryBean
将会被注入。如果没有使用 @Primary
,并且存在多个实现了 MyInterface
的 bean,Spring 将无法决定注入哪一个,从而引发异常。
总之,@Primary
注解是 Spring 框架中用于解决依赖注入歧义性的有用工具,可以确保容器在有多个相同类型的 bean 时能够正确地选择要注入的 bean。
# 2 如果primary无法注入到bean
会抛出 NoUniqueBeanDefinitionException
异常,指示依赖注入存在歧义,容器无法确定应该注入哪个 bean。
# 3 primary失败时自动找其他bean
如果你在 Spring 中使用
@Autowired(required = false)
或者Optional
来处理@Primary
bean 无法注入的情况,那么在没有其他同类型的 bean 时,myInterface
将会保持为null
或是一个空的Optional
。Spring 不会自动尝试注入其他同类型的 bean,因此不会将MySecondaryBean
或其他同类型的 bean 注入.
but
如果你希望在
@Primary
bean 无法注入时,自动尝试注入其他同类型的 bean,你需要编写自定义逻辑来处理这种情况。这通常涉及编写条件逻辑,以检查是否myInterface
为null
,然后手动尝试注入其他 bean,或者根据应用逻辑选择要注入的具体 bean。这不是 Spring 默认的行为,需要自己编码来实现。
举个示例,以下是一个可能的解决方案:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.annotation.PostConstruct;
import java.util.List;
@Service
public class MyService {
private MyInterface myInterface;
@Autowired(required = false)
public void setMyInterface(MyInterface myInterface) {
this.myInterface = myInterface;
}
@Autowired
private List<MyInterface> allMyInterfaces;
@PostConstruct
public void initialize() {
if (myInterface == null && !allMyInterfaces.isEmpty()) {
// 在这里根据你的逻辑选择一个具体的备选 bean
// 这里示例中,遍历所有备选 bean 并选择第一个非空的 bean
for (MyInterface candidate : allMyInterfaces) {
if (candidate != null) {
myInterface = candidate;
break;
}
}
if (myInterface == null) {
throw new RuntimeException("No suitable bean found for MyInterface.");
}
}
}
// ...
}