深入源码分析Spring中的构造器注入
作者:Static_lin
链接:https://blog.csdn.net/qq_41737716
关于更多Spring深度分析的文章,可以 点击这里访问。
在往期文章中我没有提到在Spring中是如何将Bean注入到构造器,其实这个过程发生在 实例化Bean时期,由
AbstractAutowireCapableBeanFactory
的
createBeanInstance方法来做的。
若想快速得到结论,可以参照最后一节的总结。
1. 示例
先来看一个例子,看看什么是构造器注入。
这里我写了一个类,分别有两个构造器,一个是注入一个Bean的构造器,一个是注入两个Bean的构造器:
public class ConstructorAutowiredTest {
private User user;
private Role role;
public ConstructorAutowiredTest() {
}
public ConstructorAutowiredTest(User user) {
this.user = user;
}
public ConstructorAutowiredTest(User user, Role role) {
this.user = user;
this.role = role;
}
public void test(){
System.out.println("user: "+user);
System.out.println("role: "+role);
}
}
Model类User与Role我就不贴代码了,分别是有两个变量,一个id,一个name。
然后就是Spring的配置文件context.xml:
<?xml version="1.0" encoding="UTF-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.0.xsd ">
<!-- 使Spring关注Annotation -->
<context:annotation-config/>
<bean class="com.mytest.demo.model.Role" id="role">
<property name="name" value="testRole"/>
<property name="id" value="2"/>
</bean>
<bean class="com.mytest.demo.model.User" id="user">
<property name="id" value="1"/>
<property name="name" value="testUser"/>
</bean>
<bean class="com.mytest.demo.autowired.ConstructorAutowiredTest" id="test"/>
</beans>
注意,如果需要使用构造器注入,需要 <context:annotation-config /> 此自定义标签开启(关于自定义标签,在本人往期的Spring系列中有详细介绍),具体作用后面再作分析。
那么,该类三个构造器,Spring会使用哪个构造器初始化ConstructorAutowiredTest
这个Bean呢?写个测试便知:
public class TestBeanAutowiredConstructor {
public static void main(String[] args) {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext();
context.setConfigLocation("context.xml");
context.refresh();
ConstructorAutowiredTest test = (ConstructorAutowiredTest) context.getBean("test");
test.test();
}
}
执行test方法,控制台打印:
从这里我们可以看出来,此时三个构造器中Spring使用了无参构造器。
我们换一个方式,将无参构造器注释掉,看看Spring到底会使用哪个构造器呢?同样执行test方法测试,控制台打印:
此时控制台报错,大致意思是Bean的实例化失败了,没有无参的构造器方法调用。此时有个疑问,明明构造器中的参数都是Bean,为什么不能初始化,一定要使用无参的构造器呢?是否是因为有两个构造器的原因?此时我们再注释掉任意一个构造函数,使测试类只有一个带参构造函数:
// public ConstructorAutowiredTest() {
// }
public ConstructorAutowiredTest(User user) {
this.user &#