一、設值注入
設值注入是指,通過 setter 方法傳入被調用者的實例。這種注入方式簡單、直觀,因而在 Spring 的依賴注入中大量使用。
構建兩個Bean:
public class School {
private String name;
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "School{" +
"name='" + name + '\'' +
'}';
}
}
public class Student {
private String username;
private String password;
private School school;
public void setSchool(School school) {
this.school = school;
}
public void setUsername(String username) {
this.username = username;
}
public void setPassword(String password) {
this.password = password;
}
@Override
public String toString() {
return "Student{" +
"username='" + username + '\'' +
", password='" + password + '\'' +
", school=" + school +
'}';
}
}
<?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="school" class="cn.lwb.spring.setterInject.School">
<property name="name" value="sichuan"/>
</bean>
<bean id="student" class="cn.lwb.spring.setterInject.Student">
<property name="username" value="lwb" />
<property name="password" value="520" />
<property name="school" ref="school"/>
</bean>
</beans>
@org.junit.Test
public void test1() {
String config = "cn/lwb/spring/setterInject/applicationContext.xml";
ApplicationContext applicationContext = new ClassPathXmlApplicationContext(config);
Student student = (Student) applicationContext.getBean("student");
System.out.println(student);
}
輸出結果:
當指定 bean 的某屬性值爲另一 bean 的實例時,通過 ref 指定它們間的引用關係。 ref的值必須爲某 bean 的 id 值。
二、構造注入
構造注入是指,在構造調用者實例的同時,完成被調用者的實例化。即,使用構造器設置依賴關係。
public Student(String username, String password, School school) {
this.username = username;
this.password = password;
this.school = school;
}
<!--構造器注入,索引注入-->
<bean id="student1" class="cn.lwb.spring.setterInject.Student">
<constructor-arg index="0" value="lwb"/>
<constructor-arg index="1" value="520" />
<constructor-arg index="2" ref="school"/>
</bean>
<!--注入順序必須與構造器中參數的順序一致-->
<bean id="student2" class="cn.lwb.spring.setterInject.Student">
<constructor-arg value="lwb"/>
<constructor-arg value="520" />
<constructor-arg ref="school"/>
</bean>
<!--根據構造器參數名稱注入-->
<bean id="student3" class="cn.lwb.spring.setterInject.Student">
<constructor-arg name="username" value="lwb"/>
<constructor-arg name="password" value="520" />
<constructor-arg name="school" ref="school"/>
</bean>
三、命名空間注入
對於設值注入與構造注入,在配置文件中,除了使用<property/>或<constructor-arg/>標籤外,還可使用命名空間注入的方式,讓注入的以<bean/>標籤屬性的方式出現。根據注入實現方式的不同,分爲 p 命名空間注入與 c 命名空間注入。
p 命名空間注入:採用設值注入方式,故需要有相應的 setter
c 命名空間注入:採用構造注入方式,故需要有相應的構造器
- p 命名空間設值注入
p命名空間設值注入,引入命名空間約束:xmlns:p="http://www.springframework.org/schema/p",在文檔中搜索p:name,便可以找到文檔例子
2. C命名空間構造注入
依然在文檔中搜索,可以找到例子:
四、集合屬性注入
<?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:p="http://www.springframework.org/schema/p"
xmlns:c="http://www.springframework.org/schema/c"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="school1" class="cn.lwb.spring.connectionInject.School" p:name="清華大學"/>
<bean id="school2" class="cn.lwb.spring.connectionInject.School" p:name="北京大學"/>
<bean id="student" class="cn.lwb.spring.connectionInject.Student">
<property name="myMap">
<map>
<entry key="張三" value="18"/>
<entry key="李四" value="18"/>
<entry key="王五" value="18"/>
</map>
</property>
<property name="myList">
<list>
<ref bean="school1"/>
<ref bean="school2"/>
</list>
</property>
<property name="myPro">
<props>
<prop key="name">lwb</prop>
<prop key="age">18</prop>
</props>
</property>
<property name="mySet">
<set>
<value>清華</value>
<value>北大</value>
</set>
</property>
<property name="myStrs">
<array>
<value>中國</value>
<value>四川</value>
<value>成都</value>
</array>
</property>
</bean>
</beans>
其中值爲簡單屬性的Set/List/Array可以用簡寫的方式:
<property name="mySet" value="清華,北大" />
<property name="myStrs" value="中國,四川,成都" />
五、對於域屬性的自動注入
對於域屬性的注入,也可不在配置文件中顯示的注入。可以通過爲<bean/>標籤設置autowire 屬性值,爲域屬性進行隱式自動注入。根據自動注入判斷標準的不同,可以分爲兩種:
byName:根據名稱自動注入
byType:根據類型自動注入
1、byName 方式自動注入
當配置文件中被調用者 Bean 的 id 值與代碼中調用者 Bean 類的屬性名相同時,可使用byName 方式,讓容器自動將被調用者 Bean 注入給調用者 Bean。容器是通過調用者的 Bean類的屬性名與配置文件的被調用者 bean 的 id 進行比較而實現自動注入的。
2、byType 方式自動注入
使用 byType 方式自動注入,要求:配置文件中被調用者 bean 的 class 屬性指定的類,要與代碼中調用者 Bean 類的某域屬性類型同源。即要麼相同,要麼有 is-a 關係(子類,或是實現類)。但這樣的同源的被調用 bean 只能有一個。多於一個,容器就不知該匹配哪一個了。
六、SPEL
spring可以通過SPEL表達式來注入值,同時也可以使用一個Bean調用另一個Bean的方法來注入值:
public class Person {
private String pusernmae;
private int page;
public String getPusernmae() {
return pusernmae;
}
public void setPusernmae(String pusernmae) {
this.pusernmae = pusernmae;
}
public int getPage() {
return page;
}
public void setPage(int page) {
this.page = page;
}
@Override
public String toString() {
return "Person{" +
"pusernmae='" + pusernmae + '\'' +
", page='" + page + '\'' +
'}';
}
public int getAge() {
return page > 20 ? 20 : page;
}
}
public class Student {
private String username;
private int age;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Student{" +
"username='" + username + '\'' +
", age=" + age +
'}';
}
}
<bean id="person" class="cn.lwb.spring.SPEL.Person">
<property name="page" value="#{T(java.lang.Math).random() * 50}" />
<property name="pusernmae" value="張三" />
</bean>
<bean id="student" class="cn.lwb.spring.SPEL.Student">
<property name="username" value="王五" />
<!--<property name="age" value="#{person.page > 25 ? 20 : person.page}"/>-->
<property name="age" value="#{person.getAge()}"/>
</bean>
由上面的xml配置可以看見,SPEL既可以通過java函數表達式來注入值,也可以通過調用別的Bean的方法或者屬性來給自己注入值。