我们平时工作中使用Spring的时候,大多数情况下是这样的:
@Service
public class UserService {
@Autowired
private OrderService orderService;
}
我们不会去给这个类特意的添加构造方法,一般都是使用默认的无参构造了。
而我们注入属性,也是用@Autowired
或者@Resource
注解来完成依赖注入。
思考一下,如果我们的一个类中有多个构造方法呢?Spring创建这个Bean的时候肯定要使用这个类的构造方法实例化,自然要确定一个构造方法。关于构造方法的确定,请查看这个文章:。
这里想明确一下,其实我们也可以使用构造方法来进行属性注入:
@Service
public class OrderService {
public UserService userService;
public StockService stockService;
public OrderService(UserService userService, StockService stockService) {
this.userService = userService;
this.stockService = stockService;
}
}
此时OrderService类中只有一个构造方法,所以Spring实例化的时候只能选择该构造方法,而且这个构造方法有两个参数,所以Spring会根据构造方法参数的类型和名称去容器中寻找并唯一确定一个Bean,然后将其注入到属性上去。所以,上面类中的userService和stockService都是有值的,已经对应了一个Bean。
测试验证:
public class Test {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
OrderService orderService = (OrderService) context.getBean("orderService");
System.out.println("===================" + orderService.getUserService());
System.out.println("===================" + orderService.getStockService());
}
}
那如果我们类中有多个构造呢?
多个构造方法(不包含无参构造)
@Service
public class OrderService {
public UserService userService;
public StockService stockService;
public OrderService(UserService userService, StockService stockService) {
this.userService = userService;
this.stockService = stockService;
}
public OrderService(UserService userService) {
this.userService = userService;
}
}
此时OrderService 类中有两个构造方法,并且没有无参构造。
此时我们运行测试类,再来看结果:<font color="red">Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.jihu.service.OrderService]: No default constructor found; nested exception is java.lang.NoSuchMethodException: com.jihu.service.OrderService.<init>()
发现此时报错了,因为我们此时没有指定Spring要使用哪个构造方法(可以将@Autowired添加到构造方法上),所以Spring默认回去找无参构造,如果找到了就使用,找不到就报错!
@Service
public class OrderService {
public UserService userService;
public StockService stockService;
public OrderService(UserService userService, StockService stockService) {
this.userService = userService;
this.stockService = stockService;
}
public OrderService() {
}
}
我们再来测试,看看结果:
可以看到,此时OrderService类是被成功创建为了一个Bean,但是里面的属性都是null。说明这里使用了无参构造来实例化。此时我们如果想完成依赖注入,可以给属性添加@Autowired
注解。
@Service
public class OrderService {
@Autowired
public UserService userService;
@Autowired
public StockService stockService;
public OrderService(UserService userService, StockService stockService) {
this.userService = userService;
this.stockService = stockService;
}
public OrderService() {
}
}
这样呢?
@Service
public class OrderService {
@Autowired
public UserService userService;
public StockService stockService;
@Autowired
public OrderService(UserService userService, StockService stockService) {
this.userService = userService;
this.stockService = stockService;
}
}
不管是构造注入还是属性注入,只要注入一次就可以了。
总结
类的构造方法也可以注入属性,而且和属性上直接添加@Autowired
并不冲突,两者是可以相互补充的。
唯一需要注意的是,无参构造是很重要的,因为它是我们类实例化的必须条件,如果我们自己写了多个构造方法,要么使用@Autowired
指定要使用的构造方法,要么保证存在无参构造,否则会报错!!!