依赖注入原理
参考文章:https://www.51cto.com/article/716969.html
Spring 中的依赖注入是通过反射来实现的,当 IOC 容器创建 Bean 的时候,会检查 Bean 中定义的依赖关系,并且尝试通过反射来注入这些依赖关系
Spring 的依赖注入有三种方式:
-
属性注入
java@RestController public class UserController { // 属性对象 @Autowired private UserService userService; @RequestMapping("/add") public UserInfo add(String username, String password) { return userService.add(username, password); } }
优点:
- 使用简单,添加
@Autowired
即可
缺点:
-
无法注入一个不可变对象(final 修饰),因为 Java 中的 final 对象,要么初始直接赋值,要么在构造方法中赋值,如果使用属性注入 final 对象,不符合 Java 的 final 使用规范
java@Autowired private final UserService userService;
-
与 IOC 容器耦合度过高,只能适用于 IOC 容器,其他非 IOC 框架不一定支持属性注入
-
可能违背单一职责原则,通过属性注入比较简单,可能造成滥用,在一个类中引入多个属性依赖,引入的越多则承担了越多的责任,违背单一职责原则的可能性越大
- 使用简单,添加
-
Setter 注入
java@RestController public class UserController { // Setter 注入 private UserService userService; @Autowired public void setUserService(UserService userService) { this.userService = userService; } @RequestMapping("/add") public UserInfo add(String username, String password) { return userService.add(username, password); } }
优点:
- setter 注入只针对一个对象,符合单一职责原则
缺点:
- 不能注入不可变对象(final 修饰的对象)
- 注入的对象可被修改(在注入之后,如果在其他地方调用 setXX 会改变注入的对象)
-
构造方法注入
Spring 4.x 之后推荐的注入方式
如果只有一个构造方法,可以不用在构造方法上添加
@Autowired
,如下边代码,可以去掉@Autowired
注解:java@RestController public class UserController { // 构造方法注入 private UserService userService; @Autowired public UserController(UserService userService) { this.userService = userService; } @RequestMapping("/add") public UserInfo add(String username, String password) { return userService.add(username, password); } }
优点:
- 可以注入不可变对象
- 注入对象不会被修改
- 通用性更好,无论是 IOC 框架还是非 IOC 框架,构造方法注入的代码都是通用的