Bean实例在调用无参构造器创建了空值对象后,就要对Bean对象的属性进行初始化。初始化是由容器自动完成的,成为注入。根据注入方式的不同,常用的有两类:设值注入、构造注入。
还有一种实现特定接口的注入。由于采用侵入式编程,污染代码,所以几乎不用
记住:所有的Bean类都要注册到配置文件里!!!
设值注入
通过setter方法传入被调用者的实例(大量使用),这种注入方式简单、直观。
实体类
public class Student {
private String name;
private int age;
private School school; //域属性,对象属性
public void setName(String name) {
this.name = name;
}
public void setAge(int age) {
this.age = age;
}
public void setSchool(School school) {
this.school = school;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
", school=" + school +
'}';
}
}
public class School {
private String name;
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "School{" +
"name='" + name + '\'' +
'}';
}
}
配置文件
<!--注册School-->
<bean id="mySchool" class="com.chen.service.School">
<property name="name" value="university"/>
</bean>
<!--注册Student-->
<bean id="myStudent" class="com.chen.service.Student">
<property name="name" value="allen"/>
<property name="age" value="24"/>
<property name="school" ref="mySchool"/>
</bean>
测试
@Test
public void testStudent() {
ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
Student student = (Student) ac.getBean("myStudent");
System.out.println(student);
}
结果:
Student{name='allen', age=24, school=School{name='university'}}
构造注入
构造注入是指,在构造调用者实例的同时,完成被调用者的实例化。即使用构造器设置依赖关系
第一种形式
实体类
public class Student2 {
private String name;
private int age;
private School school; //域属性,对象属性
public Student2() {
}
public Student2(String name, int age, School school) {
this.name = name;
this.age = age;
this.school = school;
}
//setter()方法
}
配置文件
<!--注册Student2-->
<bean id="myStudent2" class="com.chen.service.Student2">
<constructor-arg index="0" value="Chen"/>
<constructor-arg index="1" value="24"/>
<constructor-arg index="2" ref="mySchool"/>
</bean>
测试
@Test
public void testStudent2() {
ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
Student2 student2 = (Student2) ac.getBean("myStudent2");
System.out.println(student2);
}
结果
Student2{name='Chen', age=24, school=School{name='清华大学'}}
第二种形式(构造注入中最常用的方式,但是工作中最常用的注入方式是设值注入)
配置文件中的修改
<bean id="myStudent2" class="com.chen.service.Student2">
<constructor-arg name="name" value="allen"/>
<constructor-arg name="age" value="24"/>
<constructor-arg name="school" ref="mySchool"/>
</bean>
命名空间注入(仅作了解)
- p命名空间设值注入:采用设值注入方式,故需要哟uxiangying的setter()方法
- c命名空间构造注入:采用构造注入方式,故需要有相应的构造器
对于设值注入与构造注入,在配置文件中,除了使用<property/>或者<constructor-arg/>标签外,还可以使用命名空间注入的方式,让注入的值以<bean/>标签属性的方式出现,根据注入实现方式的不同,分为p命名空间注入与c命名空间注入。
集合属性注入(重点)
方式一(繁杂)
实体类
public class Collections {
private School[] schools;
private String[] myStrs;
private List<String> myList;
private Set<String> mySet;
private Map<String, Object> myMap;
private Properties myProperties;
//setter()/toString()方法
}
配置文件
<!--注册School-->
<bean id="mySchool" class="com.chen.service.School">
<property name="name" value="清华大学"/>
</bean>
<bean id="mySchool2" class="com.chen.service.School">
<property name="name" value="北京大学"/>
</bean>
<!--注册Collections-->
<bean id="myCollections" class="com.chen.service.Collections">
<property name="schools">
<array>
<ref bean="mySchool"/>
<ref bean="mySchool2"/>
</array>
</property>
<property name="myStrs">
<array>
<value>北京</value>
<value>上海</value>
</array>
</property>
<property name="myList">
<list>
<value>深圳</value>
<value>杭州</value>
</list>
</property>
<property name="mySet">
<set>
<value>成都</value>
<value>重庆</value>
</set>
</property>
<property name="myMap">
<map>
<entry key="mobile" value="1234"/>
<entry key="mobile2" value="5667"/>
</map>
</property>
<property name="myProperties">
<props >
<prop key="education">university</prop>
<prop key="gender">male</prop>
</props>
</property>
</bean>
测试
@Test
public void testCollections() {
ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
Collections collections = (Collections) ac.getBean("myCollections");
System.out.println(collections);
}
结果
Collections{schools=[School{name='清华大学'}, School{name='北京大学'}], myStrs=[北京, 上海], myList=[深圳, 杭州], mySet=[成都, 重庆], myMap={mobile=1234, mobile2=5667}, myProperties={gender=male, education=university}}
方式二(较为简单的方式)
修改xml配置文件即可
<!--注册School-->
<bean id="mySchool" class="com.chen.service.School">
<property name="name" value="清华大学"/>
</bean>
<bean id="mySchool2" class="com.chen.service.School">
<property name="name" value="北京大学"/>
</bean>
<!--注册Collections-->
<bean id="myCollections" class="com.chen.service.Collections">
<property name="schools">
<array>
<ref bean="mySchool"/>
<ref bean="mySchool2"/>
</array>
</property>
<property name="myStrs" value="北京, 上海"/>
<property name="myList" value="深圳, 杭州"/>
<property name="mySet" value="成都, 重庆"/>
<property name="myMap">
<map>
<entry key="mobile" value="1234"/>
<entry key="mobile2" value="5667"/>
</map>
</property>
<property name="myProperties">
<props >
<prop key="education">university</prop>
<prop key="gender">male</prop>
</props>
</property>
</bean>
使用SPEL注入
spel,Spring Expression Langurage,即Spring EL表达式语言。
在Spring配置文件中为Bean的属性注入值时,可直接使用SPEL表达式计算的结果。SPEL表达式以#开头,后跟一对大括号。用法:<bean id=“abc” value="#{…}"/>。
实体类
public class Person {
private String pname;
private int page;
//getter()/setter()/toString()
}
public class Student3 {
private String name;
private int age;
//getter()/setter()/toString()
}
xml配置
<!--注册Person-->
<bean id="myPerson" class="com.chen.service.Person">
<property name="pname" value="Wang"/>
<property name="page" value="#{T(java.lang.Math).random() * 50}"/>
</bean>
<!--注册Student3-->
<bean id="myStudent3" class="com.chen.service.Student3">
<property name="name" value="#{myPerson.pname}"/>
<property name="age" value="#{myPerson.page > 25 ? 25 : myPerson.page}"/>
</bean>
测试类
@Test
public void testSPEL() {
ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
Person person = (Person) ac.getBean("myPerson");
System.out.println(person);
Student3 student3 = (Student3) ac.getBean("myStudent3");
System.out.println(student3);
}
测试结果
Person{pname='Wang', page=27}
Student3{name='Wang', age=25}
以下三个内容仅作了解
1、使用内部Bean注入
<bean id="myStudent" class="com.chen.service.Student">
<property name="name" value="allen"/>
<property name="age" value="24"/>
<property name="school">
<bean class="com.chen.service.School">
<property name="name" value="清华大学"/>
</property>
</bean>
2、同类抽象Bean
实体类
public class Student4 {
String name;
int age;
String school;
String department;
//getter()/setter()/toString()
}
xml配置
<!-- ==================== 同类抽象Bean =================================== -->
<!--注册Student4-->
<bean id="baseStudent4" class="com.chen.service.Student4" abstract="true">
<property name="school" value="清华大学"/>
<property name="department" value="计算机学院"/>
</bean>
<bean id="myStudent4_1" parent="baseStudent4">
<property name="name" value="allen"/>
<property name="age" value="24"/>
</bean>
<bean id="myStudent4_2" parent="baseStudent4">
<property name="name" value="wang"/>
<property name="department" value="27"/>
</bean>
<bean id="myStudent4_3" parent="baseStudent4">
<property name="name" value="Hao"/>
<property name="age" value="24"/>
</bean>
测试
@Test
public void testStudent4() {
ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
Student4 student4_1 = (Student4)ac.getBean("myStudent4_1");
Student4 student4_2 = (Student4)ac.getBean("myStudent4_2");
Student4 student4_3 = (Student4) ac.getBean("myStudent4_3");
System.out.println(student4_1);
System.out.println(student4_2);
System.out.println(student4_3);
}
结果
Student4{name='allen', age=24, school='清华大学', department='计算机学院'}
Student4{name='wang', age=27, school='清华大学', department='计算机学院'}
Student4{name='Hao', age=24, school='清华大学', department='计算机学院'}
3、异类抽象Bean
实体类
public class Teacher {
private String name;
private int workage; //工龄
private String school; //学校
private String department; //院系
//getter()/setter()/toString()
}
public class Student5 {
String name;
int age;
String school;
String department;
//getter()/setter()/toString()
}
xml配置
<!-- ==================== 异类抽象Bean =================================== -->
<bean id="baseBean" abstract="true">
<property name="school" value="清华大学"/>
<property name="department" value="计算机系"/>
</bean>
<bean id="myStudent5" class="com.chen.service.Student5" parent="baseBean">
<property name="name" value="alen walker"/>
<property name="age" value="20"/>
</bean>
<!--注册Teacher-->
<bean id="myTeacher" class="com.chen.service.Teacher" parent="baseBean">
<property name="name" value="Zhang"/>
<property name="workage" value="18"/>
</bean>
测试
@Test
public void testTeacher() {
ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
Student5 student5 = (Student5)ac.getBean("myStudent5");
Teacher teacher = (Teacher)ac.getBean("myTeacher");
System.out.println(student5);
System.out.println(teacher);
}
为应用指定多个Spring配置文件
在实际应用里,随着应用规模的增加,系统中Bean数量也大量增加,导致配置文件变的非常庞大,臃肿。为了避免这种情况的产生,提高配置文件的可读性与可维护性,可以将Spring配置文件分解成多个配置文件。
- 平等关系的配置文件(用的是最多的)
将配置文件分解为地位平等的多个配置文件,并将所有配置文件的路径定义为一个String数组,将其作为容器初始化参数出现。其将与可变参的容器构造器匹配。
配置文件
spring-base.xml
<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="baseBean" abstract="true">
<property name="school" value="清华大学"/>
<property name="department" value="计算机系"/>
</bean>
spring-beans.xml
<bean id="myStudent5" class="com.chen.service.Student5" parent="baseBean">
<property name="name" value="alen walker"/>
<property name="age" value="20"/>
</bean>
<!--注册Teacher-->
<bean id="myTeacher" class="com.chen.service.Teacher" parent="baseBean">
<property name="name" value="Zhang"/>
<property name="workage" value="18"/>
</bean>
测试
@Test
public void testMultipyXml() {
/*
第一种方式
String resource1 = "spring-base.xml";
String resource2 = "spring-beans.xml";
ApplicationContext ac = new ClassPathXmlApplicationContext(resource1, resource2);
*/
/*
第二种方式
String[] resource = {"spring-base.xml", "spring-beans.xml"};
ApplicationContext ac = new ClassPathXmlApplicationContext(resource);
*/
/*
第三种方式(项目常用方式)
String resource = "spring-*.xml";
ApplicationContext ac = new ClassPathXmlApplicationContext(resource);
*/
String resource = "spring-*.xml";
ApplicationContext ac = new ClassPathXmlApplicationContext(resource);
Student5 student5 = (Student5) ac.getBean("myStudent5");
Teacher teacher = (Teacher) ac.getBean("myTeacher");
System.out.println(student5);
System.out.println(teacher);
}
- 包含关系
xml配置文件
applcationContext1.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">
<import resource="classpath:spring-base.xml"/>
<import resource="classpath:spring-beans.xml"/>
</beans>
spring-base.xml
<bean id="baseBean" abstract="true">
<property name="school" value="清华大学"/>
<property name="department" value="计算机系"/>
</bean>
spring-beans.xml
<bean id="myStudent5" class="com.chen.service.Student5" parent="baseBean">
<property name="name" value="alen walker"/>
<property name="age" value="20"/>
</bean>
<!--注册Teacher-->
<bean id="myTeacher" class="com.chen.service.Teacher" parent="baseBean">
<property name="name" value="Zhang"/>
<property name="workage" value="18"/>
</bean>
测试
@Test
public void testContains() {
String resource = "applicationContext1.xml";
ApplicationContext ac = new ClassPathXmlApplicationContext(resource);
Student5 student5 = (Student5) ac.getBean("myStudent5");
Teacher teacher = (Teacher) ac.getBean("myTeacher");
System.out.println(student5);
System.out.println(teacher);
}
结果
Student4{name='alen walker', age=20, school='清华大学', department='计算机系'}
Teacher{name='Zhang', workage=18, school='清华大学', department='计算机系'}