一、设值注入
设值注入是指,通过 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的方法或者属性来给自己注入值。