基于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的时候必须使用构造注入。