今天和同事讨论到Spring自动注入时,发现有这么一段代码特别地困惑,固然大体的原理仍是能够理解的,只不过之前历来没有这么用过。想到将来可能会用到,或者将来看别人写的代码时不至于花时间解决一样的困惑,因此小编仍是以为有必要研究记录一下。java
首先让咱们先看下这段代码是什么?spring
@Autowired
private XiaoMing xiaoming;
@Autowired
private XiaoMing wanger;
复制代码
XiaoMing.java
json
package com.example.demo.beans.impl;
import org.springframework.stereotype.Service;
/**
*
* The class XiaoMing.
*
* Description:小明
*
* @author: huangjiawei
* @since: 2018年7月23日
* @version: $Revision$ $Date$ $LastChangedBy$
*
*/
@Service
public class XiaoMing {
public void printName() {
System.err.println("小明");
}
}
复制代码
咱们都知道@Autowired
能够根据类型(Type
)进行自动注入,而且默认注入的bean为单例(SingleTon
)的,那么咱们可能会问,上面注入两次不会重复吗?答案是确定的。并且每次注入的实例都是同一个实例。下面咱们简单验证下:bash
@RestController
public class MyController {
@Autowired
private XiaoMing xiaoming;
@Autowired
private XiaoMing wanger;
@RequestMapping(value = "/test.json", method = RequestMethod.GET)
public String test() {
System.err.println(xiaoming);
System.err.println(wanger);
return "hello";
}
}
复制代码
调用上面的接口以后,将输出下面内容,能够看出二者为同一实例。app
com.example.demo.beans.impl.XiaoMing@6afd4ce9
com.example.demo.beans.impl.XiaoMing@6afd4ce9
复制代码
若是咱们要注入的类型声明为一个接口类型,并且该接口有1个以上的实现类,那么下面这段代码还可以正常运行吗?咱们假设Student
为接口,WangEr
和XiaoMing
为两个实现类。ui
@Autowired
private Student stu1;
@Autowired
private Student stu2;
复制代码
@Service
public class XiaoMing implements Student {
复制代码
@Service
public class WangEr implements Student {
复制代码
答案是上面的代码不能正常运行,并且Spring 还启动报错了,缘由是Spring想为Student
注入一个单例的实例,但在注入的过程当中意外地发现两个,因此报错,具体错误信息以下:spa
Field stu1 in com.example.demo.controller.MyController required a single bean, but 2 were found:
- wangEr: defined in file [C:\Users\huangjiawei\Desktop\demo\target\classes\com\example\demo\beans\impl\WangEr.class]
- xiaoMing: defined in file [C:\Users\huangjiawei\Desktop\demo\target\classes\com\example\demo\beans\impl\XiaoMing.class]
复制代码
那该怎么弄才行呢?通常思路咱们会想到为每一个实现类分配一个id值,结果就有了下面的代码:code
@Autowired
private Student stu1;
@Autowired
private Student stu2;
复制代码
@Service("stu1")
public class XiaoMing implements Student {
复制代码
@Service("stu2")
public class WangEr implements Student {
复制代码
作完上面的配置以后,Spring就会根据字段名称默认去bean工厂找相应的bean进行注入,注意名称不可以随便取的,要和注入的属性名一致。接口
@Autowired
注入屡次,而且全部注入的实例都是同一个实例;