前言
咱们都知道在 Spring Bean 的注入方式通常分为三种:一、构造器注入 二、Setter注入 三、基于注解的 @Autowired
自动装配(Field 注入)java
在以往的项目开发过程当中,咱们大多会使用方便灵活的 @Autowired
自动装配的方式来管理依赖,可是 Spring 官方却不推荐这么作
spring
Inspection info: Spring Team recommends: “Always use constructor based dependency injection in your beans. Always use assertions for mandatory dependencies”.缓存
从上述信息中咱们能够得知,Spring 团队建议咱们使用构造注入的方式管理咱们的依赖,对强制依赖使用断言,那么为何不建议使用自动装配呢app
对比构造注入和Field注入
我么能够先来对比 Field 注入和 构造器注入的区别函数
Field 注入
// Field注入 public class AClass(){ @Autowired`在这里插入代码片` private BClass BClass; }
优势
- 代码少,简洁明了
- 新增依赖十分方便,不须要修改原有代码
- 注入简单,只须要使用
@Autowired
注解或者@Resource
注解
缺点
- 容易出现空指针异常,Field 注入容许构建对象实例的时候依赖的示例对象为空,这就致使了空指针异常没法尽早的暴露出来
- 对单元测试不友好,若是使用 Field 注入,那么进行单元测试就须要初始化整个Spring 环境,将全部 Bean 实例化
- 会出现循环依赖的隐患
- 容易破坏单一职责原则
构造器注入
// 构造器注入 public class AClass(){ // 用 final 修饰,听从依赖不可变原则 private final BClass bClass; public AClass(BClass bClass){ this.bClass = bClass; } }
优势
- 解决了依赖循环的问题(spring 的三层缓存机制)
- 强依赖处理,在编译阶段就能暴露出问题
- 方便单元测试
- 能够明确的指出依赖关系
缺点
- 代码冗余,阅读不友好
使用 Lombok 解决构造器注入代码冗余问题
针对构造器注入致使代码过于繁重的问题,咱们能够经过 lombok 插件来解决这个问题,使用lombok 的
@RequiredArgsConstructor
注解生成一个包含全部常量的构造器单元测试@RequiredArgsConstructor为每一个须要特殊处理的字段生成一个带有1个参数的构造函数。全部未初始化的final字段都将得到一个参数,以及任何标记为@NonNull且未在声明位置初始化的字段。对于那些用@NonNull标记的字段,还将生成显式null检查。若是用于标记为@NonNull的字段的任何参数包含null,则构造函数将抛出NullPointerException。参数的顺序与字段在类中出现的顺序相匹配测试
@Service @RequiredArgsConstructor public class LogServiceImpl implements LogService { private final LogRepository logRepository; private final LogErrorMapper logErrorMapper; } // 实际效果等同于 @Service public class LogServiceImpl implements LogService { private final LogRepository logRepository; private final LogErrorMapper logErrorMapper; public LogServiceImpl(final LogRepository logRepository, final LogErrorMapper logErrorMapper) { this.logRepository = logRepository; this.logErrorMapper = logErrorMapper; } }