目录
引言
1、Bean的注入
1.1、Setter方法
1.2、字段注入
1.3、构造器注入
2、@Autowired和@Resource
2.1、@Autowired
2.2、@Resource
3、优雅的构造器注入
3.1、为什么不推荐@Autowired和@Resource
3.2、lombok的@RequiredArgsConstructor
引言
有的公司在SpringBoot禁止使用@Autowired和@Resource了 还有SpringBoot官方也不推荐这种形
式 IDEA编辑器也会给出提示信息不推荐
1、Bean的注入
在Spring框架中,Bean的注入方式主要有三种:构造器注入、Setter方法注入和字段注入。下面是
对这三种注入方式的介绍:
1.1、Setter方法
通过Setter方法将依赖注入到类中。这种方式允许在对象创建之后再设置依赖,适用于需要在对象
创建后进行一些初始化操作的场景。
示例:
@Service
public class MyService {
private MyRepository myRepository;
@Autowired
public void setMyRepository(MyRepository myRepository) {
this.myRepository = myRepository;
}
// 业务逻辑方法
}
1.2、字段注入
直接在字段上使用注解将依赖注入到类中。这种方式使用起来很方便,但不推荐,因为它不利于单
元测试和依赖管理。
示例:
@Service
public class MyService {
@Autowired
private MyRepository myRepository;
// 业务逻辑方法
}
1.3、构造器注入
通过构造函数参数将依赖注入到类中。这种方式在对象创建时就已经完成了依赖注入,确保了依赖
的完整性和不可变性。因此,构造器注入是推荐的注入方式。
示例:
@Service
public class MyService {
private final MyRepository myRepository;
@Autowired
public MyService(MyRepository myRepository) {
this.myRepository = myRepository;
}
// 业务逻辑方法
}
2、@Autowired和@Resource
@Autowired和@Resource在平常都是用来注入Bean 一般都用于字段注入方式 当然他们也可以构
造器注入和Setter方法注入 只是用的比较少
示例:
@Service
public class MyService {
@Autowired
private MyRepository myRepository;
// 业务逻辑方法
}
@Service
public class MyService {
@Resource
private MyRepository myRepository;
// 业务逻辑方法
}
2.1、@Autowired
这是Spring框架提供的注解,主要用于自动装配Bean。
- 按类型注入:默认情况下,
@Autowired
按类型(by type)进行注入。 - 与@Qualifier结合使用:可以与
@Qualifier
注解结合使用,以按名称(by name)进行注入。 - 构造器、Setter方法、字段注入:可以用于构造器、Setter方法和字段注入。
示例:
@Service
public class MyService {
@Autowired
private MyRepository myRepository;
// 业务逻辑方法
}
2.2、@Resource
这是Java标准的注解(来自JSR-250),也可以用于依赖注入。
特性:
- 按名称注入:默认情况下,
@Resource
按名称(by name)进行注入。 - 按类型注入:如果找不到匹配的名称,则按类型(by type)进行注入。
- Setter方法和字段注入:通常用于Setter方法和字段注入,不直接支持构造器注入。
@Service
public class MyService {
@Resource
private MyRepository myRepository;
// 业务逻辑方法
}
解释:Spring会首先尝试按名称查找一个名为myRepository
的Bean,如果找不到,再按类型查找
一个MyRepository
类型的Bean进行注入。
3、优雅的构造器注入
3.1、为什么不推荐@Autowired和@Resource
推荐使用构造器注入而不是字段注入(@Autowired
和@Resource
)的主要原因是构造器注入在设计
和测试方面具有显著优势。以下是具体原因:
1. 不可变性和线程安全
构造器注入使得依赖在对象创建时就被完全初始化,从而保证了对象的不可变性。不可变对象在多
线程环境下是线程安全的,因为它们的状态在创建之后不会改变。
2. 强制依赖
使用构造器注入可以强制依赖的存在。如果一个类的构造函数需要某个依赖,那么在创建这个类的
实例时,必须提供这个依赖,否则编译器会报错。这确保了类在使用前已经完全初始化。
3. 易于测试
构造器注入使得类更容易进行单元测试。你可以在测试中轻松地创建类的实例,并通过构造器传递
Mock或Stub对象,而不需要依赖于Spring框架的上下文。
4. 减少反射使用
字段注入和Setter方法注入通常需要使用反射机制,这可能会带来性能上的开销。构造器注入则不
需要反射,性能更优。
5. 清晰的依赖关系
构造器注入使得类的依赖关系更加明确和清晰。通过查看构造函数的参数列表,开发者可以一目了
然地知道这个类依赖于哪些其他类。
6. 避免循环依赖
构造器注入能够更好地避免循环依赖问题。在使用字段注入时,容易发生循环依赖,而构造器注入
则可以在编译时发现并解决这些问题。
7. 单一职责原则
使用构造器注入有助于遵循单一职责原则(SRP)。如果一个类需要过多的依赖,可能意味着这个
类承担了太多的职责,需要重构。
示例对比
字段注入:
@Service
public class MyService {
@Autowired
private MyRepository myRepository;
// 业务逻辑方法
}
构造器注入:
@Service
public class MyService {
private final MyRepository myRepository;
@Autowired
public MyService(MyRepository myRepository) {
this.myRepository = myRepository;
}
// 业务逻辑方法
}
3.2、lombok的@RequiredArgsConstructor
如果我们使用构造器注入 每写一个bean 就要往构造函数 添加一个 这样很麻烦
示例:
public class MyService {
private final MyRepository myRepository;
private final MyOtherDependency myOtherDependency;
public MyService(MyRepository myRepository, MyOtherDependency myOtherDependency) {
this.myRepository = myRepository;
this.myOtherDependency = myOtherDependency;
}
}
lombok提供了一个注解@RequiredArgsConstructor 只需要加上类上 编译的时候会自动帮我们生成
构造函数 我们只需要将bean声明为final类型
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
@Service
@RequiredArgsConstructor
public class MyService {
private final MyRepository myRepository;
private final MyOtherDependency myOtherDependency;
}
编译后:
import org.springframework.stereotype.Service;
@Service
public class MyService {
private final MyRepository myRepository;
private final MyOtherDependency myOtherDependency;
// 由Lombok生成的构造函数
public MyService(MyRepository myRepository, MyOtherDependency myOtherDependency) {
this.myRepository = myRepository;
this.myOtherDependency = myOtherDependency;
}
}