Spring可以通过构造函数和setter属性方法来做依赖注入,这里我们先介绍下如何使用构造函数做依赖注入。
我们要注入的类代码如下:
package cn.outofmemory.spring_DI_constructor; public class Person { private String firstName; private String lastName; private int age; private String classNo; public Person() { } public Person(String firstName, String lastName, int age, String classNo) { this.setFirstName(firstName); this.setLastName(lastName); this.setAge(age); this.setClassNo(classNo); } public Person(String firstName, int age, String classNo) { this(firstName, null, age, classNo); } public Person(String firstName, String lastName) { this(firstName, lastName, 0 , null); } public String getFirstName() { return firstName; } public void setFirstName(String firstName) { this.firstName = firstName; } public String getLastName() { return lastName; } public void setLastName(String lastName) { this.lastName = lastName; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getClassNo() { return classNo; } public void setClassNo(String classNo) { this.classNo = classNo; } }
Person类有四个属性,分别为firstName,lastName,age和classNo;有三个构造函数,无参构造函数、4个参数和3个、2个参数的构造函数。
我们在spring配置文件中通过构造函数注入,配置一个Person bean:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean class="cn.outofmemory.spring_DI_constructor.Person" id="personA"> <constructor-arg><value>James</value></constructor-arg> <constructor-arg><value>Bonde</value></constructor-arg> </bean> </beans>
配置文件中的bean指定了两个构造函数。这样spring会自动匹配到有两个参数的构造函数。我们测试一下效果,请看下面App代码:
package cn.outofmemory.spring_DI_constructor; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; /** * Hello spring! * */ public class App { public static void main( String[] args ) { ApplicationContext appContext = new ClassPathXmlApplicationContext("/spring.xml"); Person personA = (Person)appContext.getBean("personA"); System.out.println("personA firstName is " + personA.getFirstName() + ", lastName is " + personA.getLastName()); } }
运行程序将输出:
personA firstName is James, lastName is Bonde
可以看到spring正确的调用了对应的构造函数。
对于spring bean的constructor-arg节点,需要注意它的value的类型如果不指定默认情况是根据字面意思来推断的,这个有时候会容易引起混淆,比如我需要1301表示班级号,classNo是一个String类型,如果让spring默认解析的话会解析成int类型,这时候我们可以通过指定constructor-arg节点的type属性来解决。比如下面配置信息:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean class="cn.outofmemory.spring_DI_constructor.Person" id="personA"> <constructor-arg type="java.lang.String"><value>James</value></constructor-arg> <constructor-arg type="java.lang.String"><value>Bonde</value></constructor-arg> <constructor-arg type="int"><value>20</value></constructor-arg> <constructor-arg type="java.lang.String"><value>1302</value></constructor-arg> </bean> </beans>
在这个配置中我们指定了每一个构造函数参数的type属性。这样就可以避免因为参数类型导致的构造函数混淆了。
在构造函数中注入复杂类型
假定我们的Person类有一个复杂属性ContactInfo,我们也可以通过构造函数来注入这个属性,如下是ContactInfo的定义:
package cn.outofmemory.spring_DI_constructor; public class ContactInfo { private String address; private String zipCode; public ContactInfo(String address_, String zipCode_) { this.address = address_; this.zipCode = zipCode_; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } public String getZipCode() { return zipCode; } public void setZipCode(String zipCode) { this.zipCode = zipCode; } }
我们在Person类中添加Contact属性,和对应的构造函数,如下代码:
private ContactInfo contact; public ContactInfo getContact() { return contact; } public void setContact(ContactInfo contact) { this.contact = contact; } public Person(String firstName, ContactInfo contactInfo) { this.setFirstName(firstName); this.setContact(contactInfo); }
这样我们就可以在spring的配置文件中注入Person的contact属性了:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean class="cn.outofmemory.spring_DI_constructor.Person" id="personA"> <constructor-arg type="java.lang.String"><value>James</value></constructor-arg> <constructor-arg type="java.lang.String"><value>Bonde</value></constructor-arg> <constructor-arg type="int"><value>20</value></constructor-arg> <constructor-arg type="java.lang.String"><value>1302</value></constructor-arg> </bean> <bean class="cn.outofmemory.spring_DI_constructor.Person" id="personWithContact"> <constructor-arg><value>James</value></constructor-arg> <constructor-arg ref="contactOfPersonWithContact"></constructor-arg> </bean> <bean class="cn.outofmemory.spring_DI_constructor.ContactInfo" id="contactOfPersonWithContact"> <constructor-arg><value>河北省邢台市</value></constructor-arg> <constructor-arg><value>054000</value></constructor-arg> </bean> <bean class="cn.outofmemory.spring_DI_constructor.Person" id="personWithContactA"> <constructor-arg><value>James</value></constructor-arg> <constructor-arg> <bean class="cn.outofmemory.spring_DI_constructor.ContactInfo"> <constructor-arg><value>河北省邢台市</value></constructor-arg> <constructor-arg><value>054000</value></constructor-arg> </bean> </constructor-arg> </bean> </beans>
我们定义了另外两个Person:personWithContact和personWithContactA,personWithContact的contact属性是通过constructor-arg的ref属性注入进来的,而第二个person是通过直接将ContactInfo的bean写道constructor-arg节点内来实现的。
两种方法都是可用的,第一种方式适合于contact会被别的bean共享的方式,而第二种写法是不可以在其他bean之间共享的。
源码下载:spring-DI-constructor.zip
原文链接:http://outofmemory.cn/java/spring/spring-DI-via-constructor
共同学习,写下你的评论
评论加载中...
作者其他优质文章