Spring 与 IoC(第三讲)
基于 XML 的 DI
举例:Spring_DI 项目。
- 注入分类
Bean 实例在调用无参构造器创建了空值对象后,就要对 Bean 对象的属性进行初始化。初始化是由容器自动完成的,称为注入。根据注入方式的不同,常用的有两类:设值注入、构造注入。
还有另外一种,实现特定接口注入。由于这种方式采用侵入式编程,污染了代码,所以
几乎不用。
(1)设值注入
设值注入是指,通过 setter 方法传入被调用者的实例。这种注入方式简单、直观,因而在 Spring 的依赖注入中大量使用。
举例:di01_1包
当指定 bean 的某属性值为另一个 bean 的实例时,通过 ref 指定他们之间的引用关系。ref 的值必须为某 bean 的 id 值。
对于其它 Bean 对象的引用,除了 <bean/>标签的 ref 属性外,还可以使用 <ref/>标签。
(2)构造注入
构造注入是指,在构造调用者实例的同时,完成被调用者的实例化。即,使用构造器设置依赖关系。
举例:di01_2 包。
<constructor-arg/>标签中用于指定参数的属性有:
name:
指定参数名称。
index:
指明该参数对应着构造器的第几个参数,从0开始。不过,该属性不要也行,
但要注意,若参数类型相同,或之间有包含关系,则需要保证赋值顺序要与构造器中的参数顺序一致。
另外,type 属性可用于指定其类型。基本类型直接写类型关键字即可,非基本类型需要写全限定性类名。
- 命名空间注入(了解)
对于设值注入与构造注入,在配置文件中,除了使用<property/>或<constructor-arg/>标签外,还可使用命名空间注入的方式,让注入的值以<bean/>标签属性的方式出现。根据注入实现方式的不同,分为 p 命名空间注入与c命名空间注入。
p命名空间注入:采用设值注入方式,故需要有相应的setter。
c命名空间注入:采用构造注入方式,故需要有相应的构造器。
(1)p 命名空间设值注入
对于设值注入,也可使用 p 命名空间的方式进行注入。
举例: di02_01 包。
Step1:
修改配置文件头,即添加相应约束,在其中声明p命名空间。该约束在 Spring 框架解压目录\docs\spring-framework-reference\htmlsinglelindex.html中。Ctrl+F,对 p-namespace 进行检索。第一个检索结果所链接的位置即有。
Step2:
在<bean/>标签中使用 p 命名空间中的属性。
p:bean属性=“值”。 说明:该值为普通值。
p:bean属性-ref="值”。 说明: 该值为其它 beanld。
(2)c 命名空间构造注入
对于构造注入,也可以使用 c 命名空间的方式进行注入。
举例:di02_02 包。
Step1:
修改配置文件头,即添加相应约束,在其中声明 c 命名空间。该约束在 Spring 框架解压目录\docs\spring framework-reference\htmlsingle\index.html中。Ctrl+F, 对 c-namespace 进行检索。第一个检索结果所链接的位置即有。
Step2:
在<bean/>标签中使用c命名空间中的属性。
c:bean参数="值",说明:该值为普通值。
c:bean参数-ref="值",说明:该值为其它 beanld。
集合属性注入
举例:di03 包。
(1)为数组注入值
(2)为 List 注入值
(3)为 Set 注入值
(4)为 Map 注入值
(5)为 Properties 注入值
- 对于 域属性的自动注入
对于域属性的注入,也可不在配置文件中显示的注入。可以通过为<bean/>标签设置 autowire 属性值,为域属性进行隐式自动注入。根据自动注入判断标准的不同,可以分为两种:
byName:
根据名称自动注入。
byType:
根据类型自动注入。
(1)byName 方式自动注入
当配置文件中被调用者 Bean 的 id 值与代码中调用者 Bean 类的属性名相同时,可使用 byName 方式,让容器自动将被调用者 Bean 注入给调用者 Bean。容器是通过调用者的 Bean 类的属性名与配置文件的被调用者 bean 的 id 进行比较而实现自动注入的。
举例:di04_1包。
(2)byType 方式自动注入
使用 byType 方式自动注入,要求:配置文件中被调用者 bean 的 class 属性指定的类,要与代码中调用者 Bean 类的某域属性类型同源。即要么相同,要么有 is-a 关系(子类,或是实现类)。但这样的同源的被调用 bean 只能有一个。多于一个,容器就不知该匹配哪-一个了。
举例: di04_2 包。
使用 SPEL 注入
SPEL,Spring Expression Language,即 Spring EL 表达式语言。即,在 Spring 配置文件中为 Bean 的属性注入值时,可直接使用 SPEL 表达式计算的结果。SPEL 表达式以 # 开头,后跟一对大括号。 用法: <bean id="abc” value="#..}"/>。 其文档中有其用法举例。在 Spring 框架解压目录:
\docs\spring framework-reference\htmlsingle\index.html中。Ctrl+F, 对 SPEL 进行检索。第一个检索结果中 9.4.1 所链接的位置即有用法举例。
举例:di05 包。
其它用法:
(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 定义的内部。
举例: di06 包。
使用同类抽象 Bean 注入
当若干 Bean 实例同属于一个类,且这些实例的属性值又有相同值时,可以使用抽象 Bean,以简化配置文件。
抽象 Bean 是用于让其它 bean 继承的。这个 bean 在 Bean 类中是不能通过 getBean 方法获取的。设置 abstract 属性为 true 来指明该 bean 为抽象 bean,默认值为 false。 不过,该 bean 不为抽象 bean 时,也可被继承。只不过,在应用中,用于被继承的 bean 一般为抽象 bean。
举例: di07 包。
使用异类抽象 Bean 注入
当若干不同的类对象具有相同的属性,且其值也相同时,可使用异类抽象 Bean。
举例: di08 包。
为应用指定多个 Spring 配置文件
在实际应用里,随着应用规模的增加,系统中 Bean 数量也大量增加,导致配置文件变得非常庞大、臃肿。为了避免这种情况的产生,提高配置文件的可读性与可维护性,可以将 Spring 配置文件分解成多个配置文件。
(1)平等关系的配置文件
将配置文件分解为地位平等的多个配置文件,并将所有配置文件的路径定义为一个
String 数组,将其作为容器初始化参数出现。其将与可变参的容器构造器匹配。
各配置文件之间为并列关系,不分主次。
举例:di09_01 。
(2)包含关系的配置文件
各配置文件中有一个总文件,总配置文件将各其它子文件通过<import/>引入。在 Java 代码中只需要使用总配置文件对容器进行初始化即可。
举例: di09_02。
也可使用通配符*。但,此时要求父配置文件名不能满足 * 所能匹配的格式,否则将出现循环递归包含。就本例而言,父配置文件不能匹配 spring-*.xml 的格式,即不能起名为 spring-total.xml。