基于XMl的DI
1.集合属性注入
2.array数组属性注入
3.List<>属性注入
4.Set<>属性注入
5.Map<K,V>属性注入
6.Properties属性注入
7.autowire自动注入
8.SPEL注入
School类
package Part02.collectionDI; /** * Created by futao on 2017/10/10. */ public class School { private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public String toString() { return "School{" + "name='" + name + '\'' + '}'; } }
Some类
package Part02.collectionDI; import java.util.*; /** * Created by futao on 2017/10/10. */ public class Some { private School[] schools; private List<String> myList; private Set<String> mySet; private Map<String,Object> myMap; private Properties myPro; public void setSchools(School[] schools) { this.schools = schools; } public void setMyList(List<String> myList) { this.myList = myList; } public void setMySet(Set<String> mySet) { this.mySet = mySet; } public void setMyMap(Map<String, Object> myMap) { this.myMap = myMap; } public void setMyPro(Properties myPro) { this.myPro = myPro; } @Override public String toString() { return "Some{" + "schools=" + Arrays.toString(schools) + ", myList=" + myList + ", mySet=" + mySet + ", myMap=" + myMap + ", myPro=" + myPro + '}'; } }
配置文件applicationContextcollectionDI.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" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="some" class="Part02.collectionDI.Some"> <!--数组--> <property name="schools"> <array> <ref bean="school1"/> <ref bean="school2"/> <ref bean="school2"/> <ref bean="school2"/> </array> </property> <!--list--> <property name="myList"> <list> <value>张三</value> <value>李四</value> <value>王五</value> </list> </property> <!--这种方式myList的长度为1,value里面的值会被当成一个值--> <!--<property name="myList" value="张三,李四,王五"/>--> <!--set--> <property name="mySet"> <set> <value>北京</value> <value>上海</value> <value>南昌</value> </set> </property> <!--这种方式mySet的长度为1,value里面的值会被当成一个值--> <!--<property name="mySet" value="北京,上海,南昌"/>--> <!--map--> <property name="myMap"> <map> <entry key="k1" value-ref="school1"/> <entry key="k2" value-ref="school2"/> <entry key="k3" value-ref="school2"/> <entry key="k4" value-ref="school2"/> <entry key="k5" value="wechat"/> </map> </property> <property name="myPro"> <props> <prop key="地址1">上海市</prop> <prop key="地址2">闵行区</prop> <prop key="地址3">吴泾镇</prop> <prop key="地址4">紫竹</prop> <prop key="地址5">数码港</prop> </props> </property> </bean> <bean id="school1" class="Part02.collectionDI.School"> <property name="name" value="Ecjtu"></property> </bean> <bean id="school2" class="Part02.collectionDI.School"> <property name="name" value="NCDX"></property> </bean> </beans>
测试
/** * 基于XML的DI-集合属性注入 */ @Test fun test4collections(){ val classPathXmlApplicationContext = ClassPathXmlApplicationContext("applicationContextcollectionDI.xml") val some = classPathXmlApplicationContext.getBean("some") as Some println(GsonBuilder().setPrettyPrinting().create().toJson(some)) }
结果
{ "schools": [ { "name": "Ecjtu" }, { "name": "NCDX" }, { "name": "NCDX" }, { "name": "NCDX" } ], "myList": [ "张三", "李四", "王二" ], "mySet": [ "北京", "上海", "南昌" ], "myMap": { "k1": { "name": "Ecjtu" }, "k2": { "name": "NCDX" }, "k3": { "name": "NCDX" }, "k4": { "name": "NCDX" }, "k5": "wechat" }, "myPro": { "地址3": "吴泾镇", "地址2": "闵行区", "地址1": "上海市", "地址5": "数码港", "地址4": "紫竹" } }
autowire自动装配
School类
package Part02.autoDIbyNameForDomain; /** * Created by futao on 2017/10/10. */ public class School { private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public String toString() { return "School{" + "name='" + name + '\'' + '}'; } }
Student类
package Part02.autoDIbyNameForDomain; /** * Created by futao on 2017/10/10. */ public class Student { private String name; private int age; private String address; private School school; public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } public School getSchool() { return school; } public void setSchool(School school) { this.school = school; } public Student() { } public Student(String name, int age, String address, School school) { this.name = name; this.age = age; this.address = address; this.school = school; } @Override public String toString() { return "Student{" + "name='" + name + '\'' + ", age=" + age + ", address='" + address + '\'' + ", school=" + school + '}'; } }
applicationContext.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" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="school1" class="Part02.autoDIbyNameForDomain.School"> <property name="name" value="上海交通大学"/> </bean> <bean id="student" class="Part02.autoDIbyNameForDomain.Student" autowire="byName"> <property name="age" value="18"/> <property name="address" value="Shanghai"/> </bean> </beans>
测试
/** * 基于XML的DI-byName方式的域属性自动注入 */ @Test fun test4autoDIbyNamefordomain() { val classPathXmlApplicationContext = ClassPathXmlApplicationContext("applicationContextautoDIbyNameForDomain.xml") val student = classPathXmlApplicationContext.getBean("student") as Part02.autoDIbyNameForDomain.Student // serializeNulls()->为null的值也显示出来,setPrettyPrinting()->格式化控制台输出 println(GsonBuilder().serializeNulls().setPrettyPrinting().create().toJson(student)) println(student) }
结果
{ "name": null, "age": 18, "address": "Shanghai", "school": null } Student{name='null', age=18, address='Shanghai', school=null}
others
在xml配置文件中,autowire有5种类型,可以在<bean/>元素中使用autowire属性指定
<table>
<tr>
<td>模式</td>
<td>说明</td>
</tr>
<tr>
<td>no</td>
<td>不使用自动装配,必须通过ref元素指定依赖,默认设置。</td>
</tr>
<tr>
<td>byName</td>
<td> 根据属性名自动装配。此选项将检查容器并根据名字查找与属性完全一致的bean,并将其与属性自动装配。</td>
</tr>
<tr>
<td>byType</td>
<td> 如果容器中存在一个与指定属性类型相同的bean,那么将与该属性自动装配;如果存在多个该类型bean,那么抛出异常,并指出不能使用byType方式进行自动装配;如果没有找到相匹配的bean,则什么事都不发生,也可以通过设置dependency-check="objects"让Spring抛出异常。</td>
</tr>
<tr>
<td>constructor</td>
<td>与byType方式类似,不同之处在于它应用于构造器参数。如果容器中没有找到与构造器参数类型一致的bean,那么抛出异常。</td>
</tr>
<tr>
<td>autodetect </td>
<td>通过bean类的自省机制(introspection)来决定是使用constructor还是byType方式进行自动装配。如果发现默认的构造器,那么将使用byType方式。 </td>
</tr>
</table>
可以设置bean使自动装配失效:
采用xml格式配置bean时,将<bean/>
元素的autowire-candidate属性设置为false,这样容器在查找自动装配对象时,将不考虑该bean,即它不会被考虑作为其它bean自动装配的候选者,但是该bean本身还是可以使用自动装配来注入其它bean的。
需要注意以下情况:
autowird="byType" (type->A)
B extends A
A是一个bean
如果此时B也是一个bean,则会报错,该类型(A)的bean不止一个。
因为A a=new B()
B类型也可以作为A类型根据autowird="byType"进行注入
SPEL注入
Person类
package Part02.SPELDI; /** * Created by futao on 2017/10/11. */ public class Person { /** * 姓名 */ private String pname; /** * 年龄 */ private int page; /** * 带参构造方法 * * @param pname 姓名 * @param page 年龄 */ public Person(String pname, int page) { this.pname = pname; this.page = page; } public Person() { } public String getPname() { return pname; } public void setPname(String pname) { this.pname = pname; } public int getPage() { return page; } public void setPage(int page) { this.page = page; } @Override public String toString() { return "Person{" + "pname='" + pname + '\'' + ", page=" + page + '}'; } /** * 控制年龄 * * @return */ public int calculateAge() { return page > 25 ? 25 : page; } }
Student类
package Part02.SPELDI; /** * Created by futao on 2017/10/12. */ public class Student { private String sname; private int sage; public String getSname() { return sname; } public void setSname(String sname) { this.sname = sname; } public int getSage() { return sage; } public void setSage(int sage) { this.sage = sage; } @Override public String toString() { return "Student{" + "sname='" + sname + '\'' + ", sage=" + sage + '}'; } }
配置文件
<?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 id="person" class="Part02.SPELDI.Person"> <property name="pname" value="老三"/> <property name="page" value="#{T(java.lang.Math).random()*50}"/> </bean> <bean id="student" class="Part02.SPELDI.Student"> <property name="sname" value="#{person.pname}"/> <!--<property name="sage" value="#{person.page > 25 ? 25:person.page}"/>--> <property name="sage" value="#{person.calculateAge()}"/> </bean> </beans>
测试
/** * SPEL注入 */ @Test fun test4SPEL(){ val classPathXmlApplicationContext = ClassPathXmlApplicationContext("applicationContextSPEL.xml") val student = classPathXmlApplicationContext.getBean("student") as Part02.SPELDI.Student val person = classPathXmlApplicationContext.getBean("person") as Person println(GsonBuilder().serializeNulls().setPrettyPrinting().create().toJson(student)) println(GsonBuilder().serializeNulls().setPrettyPrinting().create().toJson(person)) student.sage=666 println(GsonBuilder().serializeNulls().setPrettyPrinting().create().toJson(student)) println(GsonBuilder().serializeNulls().setPrettyPrinting().create().toJson(person)) person.page=999 println(GsonBuilder().serializeNulls().setPrettyPrinting().create().toJson(student)) println(GsonBuilder().serializeNulls().setPrettyPrinting().create().toJson(person)) }
结果
{ "sname": "老三", "sage": 25 } { "pname": "老三", "page": 29 } { "sname": "老三", "sage": 666 } { "pname": "老三", "page": 29 } { "sname": "老三", "sage": 666 } { "pname": "老三", "page": 999 }
tips:
如果一个类有带参的构造函数,而没有无参的构造函数,那么在注册bean的时候必须使用构造注入。