我们平时工作中使用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());
	}
}

spring 构造方法注入重名对象 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(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() {
	}
}

我们再来测试,看看结果:

spring 构造方法注入重名对象 spring构造方法注入注解_spring 构造方法注入重名对象_02


可以看到,此时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() {
	}
}

spring 构造方法注入重名对象 spring构造方法注入注解_构造方法_03

这样呢?

@Service
public class OrderService {

	@Autowired
	public UserService userService;

	public StockService stockService;


	@Autowired
	public OrderService(UserService userService, StockService stockService) {
		this.userService = userService;
		this.stockService = stockService;
	}
}

spring 构造方法注入重名对象 spring构造方法注入注解_java_04


不管是构造注入还是属性注入,只要注入一次就可以了。

总结

类的构造方法也可以注入属性,而且和属性上直接添加@Autowired并不冲突,两者是可以相互补充的。

唯一需要注意的是,无参构造是很重要的,因为它是我们类实例化的必须条件,如果我们自己写了多个构造方法,要么使用@Autowired指定要使用的构造方法,要么保证存在无参构造,否则会报错!!!