在 Spring 中注入依赖时有字段注入、构造器注入、Setter 方法注入三种注入方式。
字段注入缺点
无法注入 final 字段
在 Spring 2.5 中引入了 @Autowired
注解,它可以对类成员变量、方法及构造函数进行标注,完成自动装配的工作。在成员变量上使用 @Autowired
注解可以进行字段注入,如下:
public class UserController {
@Autowired
private UserService userService;
}
使用起来代码简洁,简单方便,可读性强。但是 Spring 官方不建议使用这种注入方式,在 IDEA 中使用字段注入时会出现黄色波浪线,如下所示:
@Autowired
的本质是通过反射的方法完成属性注入,因此,@Autowired
会在对象创建完成之后执行,同时@Autowired
也无法在声明为 final
类型的字段上发生作用,否则会报尚未初始化错误:
因为这些字段必须在类实例化时实例化。
与 Spring 容器耦合度高
其次,使用@Autowired
字段注入会增加与 Spring 容器的耦合程度,例如在测试类中测试 UserController
的 getUser()
方法:
@Test
void contextLoads() {
UserController userController = new UserController();
userController.getUser();
}
由于在 getUser()
方法中调用了字段注入的 UserService
,所以运行时会报 NullPointerException
空指针异常:
修改为使用 Spring 容器注入依赖后解决:
@Autowired
private UserController userController;
@Test
void contextLoads() {
userController.getUser();
}
构造器注入(Spring 官方推荐)
在类构造器上使用 @Autowired
注解,在构造器中将对象注入 final
类型的字段,同时避免了出现空指针异常。
public class UserController {
private final UserService userService;
@Autowired
public UserController(UserService userService) {
this.userService=userService;
}
}
但是当需要注入的对象有很多时,构造器的参数就会增多,代码就会变得臃肿起来。那么可以使用 Lombok
提供的注解来简化操作,在类上使用 @RequiredArgsConstructor
注解,将注入的字段注为 final 类型,如下:
@RequiredArgsConstructor
public class UserController {
private final UserService userService;
}
Lombok
会自动生成含有 final 类型字段的构造器:
但是构造器注入无法解决循环依赖的问题。
Setter 方法注入
Setter 方法注入是通过 set 的方式注入依赖,如下:
public class UserController {
private UserService userService;
@Autowired
public void setUserService(UserService userService) {
this.userService = userService;
}
}
这一方式可以解决循环依赖的问题,但是也不能注入 final 类型的字段。文章来源:https://www.toymoban.com/news/detail-447466.html
总结:最好的解决方案是用构造器参数实现强制依赖,Setter 方法实现可选依赖。文章来源地址https://www.toymoban.com/news/detail-447466.html
到了这里,关于使用 @Autowired 依赖注入时警告不建议使用字段注入的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!