While discussing Spring auto injection with a colleague today, I found a piece of code that was particularly confusing. The general principles are understandable, but it has never been used this way before. I thought it would be worth researching and documenting it, considering that I might use it in the future, or that I might not spend time solving the same puzzle when I look at code written by others in the future.
One, the same type of injection multiple times for the same instance
So let’s first look at what this code is.
@Autowired
private XiaoMing xiaoming;
@Autowired
private XiaoMing wanger;
Copy the code
XiaoMing.java
package com.example.demo.beans.impl; import org.springframework.stereotype.Service; /** ** The class XiaoMing. ** Description: XiaoMing ** @author: huangjiawei * @since: July 23, 2018 * @version:$Revision$ $Date$ $LastChangedBy$
*
*/
@Service
public class XiaoMing {
public void printName() {
System.err.println("Xiao Ming"); }}Copy the code
We all know that @AutoWired can be injected automatically by Type, and that the default injected bean is a SingleTon, so we might ask, won’t the injection be repeated twice? The answer is yes. And the injected instance is the same one every time. Here’s a simple verification:
@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"; }}Copy the code
After invoking the above interface, the following output is displayed, showing that both are the same instance.
com.example.demo.beans.impl.XiaoMing@6afd4ce9
com.example.demo.beans.impl.XiaoMing@6afd4ce9
Copy the code
Inject interface type instances
If the type we are injecting is declared as an interface type and the interface has more than one implementation class, will the following code still work? We assume that Student is the interface and WangEr and XiaoMing are the two implementation classes.
@Autowired
private Student stu1;
@Autowired
private Student stu2;
Copy the code
@Service
public class XiaoMing implements Student {
Copy the code
@Service
public class WangEr implements Student {
Copy the code
The above code does not work properly, and Spring started with an error. The reason is that Spring tried to inject a singleton into Student, but found two instances during the injection process.
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]
Copy the code
So how do you do that? The general idea would be to assign an ID value to each implementation class, resulting in the following code:
@Autowired
private Student stu1;
@Autowired
private Student stu2;
Copy the code
@Service("stu1")
public class XiaoMing implements Student {
Copy the code
@Service("stu2")
public class WangEr implements Student {
Copy the code
After the above configuration, Spring will go to the bean factory by default to find the appropriate bean for injection based on the field name. Note that the name must be the same as the injected property name.
Third, summary
- 1, the same type can be used
@Autowired
Inject multiple times, and all injected instances are the same instance; - 2. When injecting interfaces, you should specify an ID for each implementation class, and Spring will report an error.