注入分类
Bean 实例在调用无参构造器创建了空值对象后,就要对 Bean 对象的属性进行初始化。初始化是由容器自动完成的, 称为注入。根据注入方式的不同, 常用的有两类: 设值注入、构造注入(接口注入几乎不用)。
设值注入
设值注入是指,通过 setter 方法传入被调用者的实例(底层通过调用 setter 方法将值注入)。这种注入方式简单、直观,因而在 Spring 的依赖注入中大量使用。
(1) 定义实体类
public class School {
private String name;
}
public class Student {
private String name;
private int age;
private School school;
public void setName(String name) {
System.out.println("执行setName()");
this.name = name;
}
}
(2) 创建 Spring 配置文件
<!-- 注册School -->
<bean id="mySchool" class="com.huang.di01.School">
<property name="name" value="清华大学"/>
</bean>
<!-- 注册Student -->
<bean id="myStudent" class="com.huang.di01.Student">
<property name="name" value="张三"/>
<property name="age" value="22"/>
<property name="school" ref="mySchool"/>
</bean>
(3) 定义测试类
@Test
public void test01() {
String resource = "com/huang/di01/applicationContext.xml";
ApplicationContext ac = new ClassPathXmlApplicationContext(resource);
Student student = (Student) ac.getBean("myStudent");
System.out.println(student);
}
(4) 运行结果
当指定 bean 的某属性值为另一 bean 的实例时,通过 ref 指定它们间的引用关系。 ref 的值必须为某 bean 的 id 值(域属性(引用类型)的注入需要使用 ref 属性,字符串和基本数据类型使用 value)。对于其它 Bean 对象的引用,除了<bean/>标签的 ref 属性外,还可以使用<ref/>标签。
构造注入
构造注入是指,在构造调用者实例的同时,完成被调用者的实例化。即,使用构造器设置依赖关系(底层调用的是构造器)。
(1) 修改实现类
(2) 修改 Spring 配置文件
<constructor-arg />标签中用于指定参数的属性有:
- name:指定参数名称。
- index:指明该参数对应着构造器的第几个参数,从 0 开始。不过,该属性不要也行,但要注意,若参数类型相同,或之间有包含关系,则需要保证赋值顺序要与构造器中的参数顺序一致。
命名空间注入
对于设值注入与构造注入,在配置文件中,除了使用<property/>或<constructor-arg/>标签外,还可使用命名空间注入的方式,让注入的值以<bean/>标签属性的方式出现。根据注入实现方式的不同,分为:
p 命名空间注入:采用设值注入方式,故需要有相应的 setter
c 命名空间注入:采用构造注入方式,故需要有相应的构造器
p 命名空间设值注入
c 命名空间构造注入
集合属性注入
(1) 定义实体类
public class Some {
private School[] schools;
private String[] myStrs;
private List<String> myList;
private Set<String> mySet;
private Map<String, Object> myMap;
private Properties myPros;
}
(2) 修改 Spring 配置文件
<!-- 注册School -->
<bean id="mySchool" class="com.huang.di05.School">
<property name="name" value="清华大学"/>
</bean>
<bean id="mySchool2" class="com.huang.di05.School">
<property name="name" value="北京大学"/>
</bean>
<!-- 注册Student -->
<bean id="mySome" class="com.huang.di05.Some">
<property name="schools">
<array>
<ref bean="mySchool"/>
<ref bean="mySchool2"/>
</array>
</property>
<!-- 为数组注入值 -->
<property name="myStrs">
<array>
<value>中国</value>
<value>广东</value>
</array>
</property>
<!-- 为 List 注入值 -->
<property name="myList">
<list>
<value>广州</value>
<value>天河</value>
</list>
</property>
<!-- 为 Set 注入值 -->
<property name="mySet">
<set>
<value>现代学院</value>
<value>信息工程系</value>
</set>
</property>
<!-- 为 Map 注入值 -->
<property name="myMap">
<map>
<entry key="mobile" value="1234567"/>
<entry key="QQ" value="7654321"/>
</map>
</property>
<!-- 为 Properties 注入值 -->
<property name="myPros">
<props>
<prop key="education">大学</prop>
<prop key="gender">男</prop>
</props>
</property>
</bean>
Spring 配置文件的简单赋值
对于域属性的自动注入
对于域属性的注入,也可不在配置文件中显示的注入。可以通过为<bean/>标签设置 autowire 属性值,为域属性进行隐式自动注入。根据自动注入判断标准的不同,可以分为两种:
- byName:根据名称自动注入
- byType:根据类型自动注入
(1) byName 方式自动注入
当配置文件中被调用者 Bean 的 id 值与代码中调用者 Bean 类的属性名相同时,可使用 byName 方式,让容器自动将被调用者 Bean 注入给调用者 Bean。容器是通过调用者的 Bean 类的属性名与配置文件的被调用者 bean 的 id 进行比较而实现自动注入的。
(2) byType 方式自动注入
使用 byType 方式自动注入,要求:配置文件中被调用者 bean 的 class 属性指定的类,要与代码中调用者 Bean 类的某域属性类型同源。即要么相同,要么有 is-a 关系(子类,或是实现类)。
使用 SPEL 注入
SPEL(Spring Expression Language),即 Spring EL 表达式语言。即,在 Spring 配置文件中为 Bean 的属性注入值时,可直接使用 SPEL 表达式计算的结果。 SPEL 表达式以#开头,后跟一对大括号。
用法: <bean id=“abc” value=“#{…}”/>。
其它用法:
(1) <property name=“school” value=“#{mySchool}”/>:引用另一个 bean。指定 school 的值为另一个 Bean 实例 mySchool。
(2) <property name=“schoolName” value=“#{mySchool.name.toUpperCase()}”/>:使用指定属性,并使用其方法。指定 schoolName 的值为 mySchool 的 name 属性值,并将其字母均转换为大写字母(toUpperCase()方法)。
使用内部 Bean 注入
若不希望代码直接访问某个 bean,即,在代码中通过 getBean 方法获取该 Bean 实例,则可将该 Bean 的定义放入调用者 bean 定义的内部。
使用同类抽象 Bean 注入
当若干 Bean 实例同属于一个类,且这些实例的属性值又有相同值时,可以使用抽象Bean,以简化配置文件。
抽象 Bean 是用于让其它 bean 继承的。这个 bean 在 Bean 类中是不能通过 getBean 方法获取的。设置 abstract 属性为 true 来指明该 bean 为抽象 bean, 默认值为 false。 不过,该 bean 不为抽象 bean 时,也可被继承。 只不过,在应用中,用于被继承的 bean 一般为抽象 bean。
使用异类抽象 Bean 注入
当若干不同的类对象具有相同的属性,且其值也相同时,可使用异类抽象 Bean。
为应用指定多个 Spring 配置文件
在实际应用里,随着应用规模的增加,系统中 Bean 数量也大量增加,导致配置文件变得非常庞大、臃肿。为了避免这种情况的产生,提高配置文件的可读性与可维护性,可以将 Spring 配置文件分解成多个配置文件。
(1)平等关系的配置文件
将配置文件分解为地位平等的多个配置文件,并将所有配置文件的路径定义为一个 String 数组,将其作为容器初始化参数出现。 其将与可变参的容器构造器匹配。
( 2)包含关系的配置文件
各配置文件中有一个总文件,总配置文件将各其它子文件通过<import/>引入。在 Java 代码中只需要使用总配置文件对容器进行初始化即可。
Spring 配置文件中也可使用通配符*。但,此时要求总配置文件不要和子配置文件命名格式相同,否则将出现循环递归包含。