依赖注入的方式
首先,要搞清楚Spring依赖注入共有哪几种方式:
- 属性注入
- Setter注入
- 构造方法注入
@Autowired和@Resource都属于是属性注入的范畴,下面是一个简单的属性注入示例:
@RestController
public class UserController {
// 属性对象
@Autowired
private UserService userService;
@RequestMapping("/add")
public UserInfo add(String username, String password) {
return userService.add(username, password);
}
}
属性注入有什么优缺点?
优点:简单
缺点如下:
- 功能性问题:不可注入一个不可变的对象(被注入的对象不能使用final修饰)
- 通用性问题:只能适用于Ioc容器
- 设计原则问题:注入实现越简单,那么滥用它的概率也越大,所以出现违背单一职责原则的概率也越大。
- 使用field注入可能会导致循环依赖,即A里面注入B,B里面又注入A,这种循环依赖的错误,启动的时候不报错,但是使用的时候会报错
下面是Setter方法注入的示例:
@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注入有什么优缺点:
优点:
- 完全符合单一职责设计原则,一个Setter只针对一个对象。
- 允许后续对对象重新注入和配置,比较灵活
缺点:
- 注入方式要比属性注入麻烦很多
- 不可注入不可变对象
- Setter 注入提供了 setXXX 的方法,所以被注入的对象可能随时被修改
下面是构造方法注入的示例:
@RestController
public class UserController {
// 构造方法注入
private UserService userService;
//如果当前类只有一个构造方法,那么这个@Autowire也可以省略
@Autowired
public UserController(UserService userService) {
this.userService = userService;
}
@RequestMapping("/add")
public UserInfo add(String username, String password) {
return userService.add(username, password);
}
}
构造函数注入有什么优缺点?
优点:
- 确保依赖不可变:被注入的对象,可以使用final修饰符,以确保这个对象不会被改变
依赖项的强制性注入:当要实例化对象的时候,由于自己实现了有参数的构造函数,所以不会调用默认无参构造函数,那么就需要Spring容器传入所需要的参数,所以就两种情况:
- 有该类型的参数->传入,OK 。
- 无该类型的参数->报错。
- 所以保证依赖对象不会为空,Spring总不至于传一个null进去吧 😦
完全初始化的状态:
- 这个可以跟上面的依赖不为空结合起来,向构造器传参之前,要确保注入的内容不为空,那么肯定要调用依赖组件的构造方法完成实例化。而在Java类加载实例化的过程中,构造方法是最后一步(之前如果有父类先初始化父类,然后自己的成员变量,最后才是构造方法,这里不详细展开。)。所以返回来的都是初始化之后的状态。
- 如果有循环依赖,项目启动的时候就会报错提醒你
@Autowired和@Resource的区别
相同点:这俩注解都是属性注入的方式,都是直接写在属性上的
不同点:
- @Autowired是Spring提供的注解,@Resource是JDK提供的注解(不用导入额外框架也可以使用)
- @Autowired是根据对象的类型来注入的,如果一个Class创建了两个对象,那么@Autowired就不知道该注入哪一个了,回报错!
-
@Resource有两个属性:name和type
- 当指定了name的时候,@Resource会根据对象的名字来进行注入
- 当指定了type的时候,@Resource会更具对象的类型来进行注入
- 如果都不指定的话,@Resouce会先根据名字注入,找不到名字就使用类型注入
如果非要使用这两个注解的话,那肯定是推荐注入机制更加完善的@Resource
最好的方式其实是使用构造函数注入的方式
《Spring依赖注入,为什么不推荐用@Autowired,而是用构造函数注入呢?》留言数:0