假设现在有一个接口:
java
public interface TestRepository {
void save();
}
然后你写了两个实现类:
java
@Repository
public class MysqlTestRepository implements TestRepository {
@Override
public void save() {
System.out.println("保存到 MySQL");
}
}
以及:
java
@Repository
public class MemoryTestRepository implements TestRepository {
@Override
public void save() {
System.out.println("保存到内存");
}
}
此时 Spring 容器里实际上有两个 Bean:
java
MysqlTestRepository
MemoryTestRepository
而且它们都属于:
java
TestRepository
这时候如果你写:
java
@Service
public class StudentService {
private final TestRepository repository;
public StudentService(TestRepository repository) {
this.repository = repository;
}
}
Spring 就懵了:
你要
TestRepository,但我这里有两个,到底给你哪个?
这时通常会启动失败。
1.@Primary:设置默认实现
你可以告诉 Spring:
如果有多个同类型 Bean,默认优先用这个。
例如:
java
@Repository
@Primary
public class MysqlTestRepository implements TestRepository {
@Override
public void save() {
System.out.println("保存到 MySQL");
}
}
另一个:
java
@Repository
public class MemoryTestRepository implements TestRepository {
}
那么:
java
public StudentService(TestRepository repository)
Spring 会默认注入:
java
MysqlTestRepository
因为它被标记了:
java
@Primary
你可以理解成:
@Primary= 默认候选人。
2.@Qualifier:明确指定我要哪个
有时候不能只设置一个默认值。
比如:
java
StudentService
→ 想用 MySQL
TestService
→ 想用 Memory
这时可以明确指定。
例如:
java
@Service
public class StudentService {
private final TestRepository repository;
public StudentService(
@Qualifier("mysqlTestRepository")
TestRepository repository) {
this.repository = repository;
}
}
这表示:
我要名字叫
mysqlTestRepository的那个 Bean。
Spring 默认会把:
MysqlTestRepository
生成的 Bean 名字变成:
mysqlTestRepository
也就是类名首字母小写。
3. 还可以自己指定 Bean 名字
比如:
java
@Repository("mysqlRepo")
public class MysqlTestRepository
implements TestRepository {
}
然后:
java
public StudentService(
@Qualifier("mysqlRepo")
TestRepository repository) {
}
这样就不依赖默认的:
mysqlTestRepository
名字了。
4.可以把 Spring 注入理解成一个匹配过程
Spring 创建:
StudentService
发现构造器需要:
TestRepository
于是去容器里找:
有没有 TestRepository 类型的 Bean?
情况一:
找到 0 个
→ 报错:没有 Bean
情况二:
找到 1 个
→ 直接注入
情况三:
找到 2 个或更多
→ 看有没有 @Qualifier
→ 没有就看有没有 @Primary
→ 还无法确定就报错
这套逻辑掌握以后,Spring 的依赖注入其实就很清楚了。