[Js-Spring]基于 XML 的 DI
Posted Js_zero
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[Js-Spring]基于 XML 的 DI相关的知识,希望对你有一定的参考价值。
注入分类
(1)设值注入:先调用 Bean 的无参构造函数,然后通过 setter 方法传入被调用者的实例。
<!-- bean definitions here --> <bean id="mySchool" class="com.neu.di01.School"> <property name="sname" value="neu"></property> </bean> <bean id="myStudent" class="com.neu.di01.Student"> <property name="name" value="js"></property> <property name="age" value="23"></property> <property name="school" ref="mySchool"></property> </bean>
注:对于其他 Bean 对象的引用,除了<bean/>标签的 ref 属性外,还可以使用 <ref/> 标签
(2)构造注入:在构造调用者实例的同时,完成了被调用者的实例化。即使用构造器设置依赖关系
<constructor-arg> 标签中用于指定参数的属性:
name:指定参数名称
index:指明该参数对应构造器的第几个参数,从0开始,不过该属性可以不需要,但是需要注意,若参数类型相同,或之间有包含关系,则需要保证赋值顺序要与构造器中的参数顺序一致
另外,type属性可用于指定类型,基本类型直接写类型关键字即可,非基本类型需要写全限定性类名
<!-- bean definitions here --> <bean id="mySchool" class="com.neu.di02.School"> <property name="sname" value="neu"></property> </bean> <bean id="myStudent" class="com.neu.di02.Student"> <constructor-arg name="name" value="js"></constructor-arg> <constructor-arg name="age" value="22"></constructor-arg> <constructor-arg name="school" ref="mySchool"></constructor-arg> <!-- <constructor-arg value="js"></constructor-arg> <constructor-arg value="22"></constructor-arg> <constructor-arg ref="mySchool"></constructor-arg> --> <!-- <constructor-arg index="0" value="js"></constructor-arg> <constructor-arg index="1" value="22"></constructor-arg> <constructor-arg index="2" ref="mySchool"></constructor-arg> --> </bean>
(3)特定接口注入:采用了侵入式编程,污染了代码,几乎不用
命名空间注入(了解)
对于设值注入和构造注入,除了使用 <property/>或<constructor-arg/>标签外,还可以使用命名空间注入的方式,让注入的值以<bean/>标签属性的方式出现。根据注入实现方式的不同,分别以 p 命名空间和 c 命名空间注入。
p 命名空间注入:采用设值注入,需要相应的 setter 方法
c 命名空间注入:采用构造注入,需要相应的构造器
(1)p 命名空间注入
采用约束
xmlns:p="http://www.springframework.org/schema/p"
<!-- bean definitions here --> <bean id="mySchool" class="com.neu.di03.School" p:sname="北京大学"></bean> <bean id="myStudent" class="com.neu.di03.Student" p:name="张三" p:age="22" p:school-ref="mySchool"></bean>
(2)c 命名空间注入
采用约束
xmlns:c="http://www.springframework.org/schema/c"
<!-- bean definitions here --> <bean id="mySchool" class="com.neu.di04.School"> <property name="sname" value="清华大学"></property> </bean> <bean id="myStudent" class="com.neu.di04.Student" c:name="张三" c:age="22" c:school-ref="mySchool"></bean>
集合属性注入
分别为数组,List,Set,Map,Properties注入值,例子如下,
School.java
package com.neu.di05; public class School { private String sname; public void setSname(String sname) { this.sname = sname; } @Override public String toString() { return "School [sname=" + sname + "]"; } }
Some.java
package com.neu.di05; import java.util.Arrays; import java.util.List; import java.util.Map; import java.util.Properties; import java.util.Set; public class Some { private School[] schools; private List<String> myList; private Set<String> mySet; private Map<String, Object> myMap; private Properties myPros; public void setSchools(School[] schools) { this.schools = schools; } public void setMyList(List<String> myList) { this.myList = myList; } public void setMySet(Set<String> mySet) { this.mySet = mySet; } public void setMyMap(Map<String, Object> myMap) { this.myMap = myMap; } public void setMyPros(Properties myPros) { this.myPros = myPros; } @Override public String toString() { return "Some [schools=" + Arrays.toString(schools) + ", myList=" + myList + ", mySet=" + mySet + ", myMap=" + myMap + ", myPros=" + myPros + "]"; } }
applicationContext.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" xmlns:c="http://www.springframework.org/schema/c" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd"> <!-- bean definitions here --> <bean id="school1" class="com.neu.di05.School"> <property name="sname" value="清华大学"></property> </bean> <bean id="school2" class="com.neu.di05.School"> <property name="sname" value="北京大学"></property> </bean> <bean id="some" class="com.neu.di05.Some"> <property name="schools"> <array> <ref bean="school1" /> <ref bean="school2" /> </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="QQ" value="123"></entry> <entry key="WeiXin" value="456"></entry> </map> </property> <property name="myPros"> <props> <prop key="地址">辽宁省沈阳市</prop> <prop key="名称">neu</prop> </props> </property> </bean> </beans>
applicationContext.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" xmlns:c="http://www.springframework.org/schema/c" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd"> <!-- bean definitions here --> <bean id="school1" class="com.neu.di06.School"> <property name="sname" value="清华大学"></property> </bean> <bean id="school2" class="com.neu.di06.School"> <property name="sname" value="北京大学"></property> </bean> <bean id="some" class="com.neu.di06.Some"> <property name="schools"> <array> <ref bean="school1" /> <ref bean="school2" /> </array> </property> <property name="arrays" value="aaa,bbb"></property> <property name="myList" value="张三s,李四"></property> <property name="mySet" value="北京,上海"></property> <property name="myMap"> <map> <entry key="QQ" value="123"></entry> <entry key="WeiXin" value="456"></entry> </map> </property> <property name="myPros"> <props> <prop key="地址">辽宁省沈阳市</prop> <prop key="名称">neu</prop> </props> </property> </bean> </beans>
MyTest.java
package com.neu.di05; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class MyTest { @Test public void test01() { // 加载Spring配置文件,创建Spring容器对象 String resource = "com/neu/di05/applicationContext.xml"; ApplicationContext ac = new ClassPathXmlApplicationContext(resource); // 从容器中获取指定的Bean对象 Some some = (Some) ac.getBean("some"); System.out.println(some); ((ClassPathXmlApplicationContext) ac).close(); } }
对于域属性的自动注入
byName 方式自动注入
配置文件中被调用者的 Bean 的 id 值与代码中调用者 Bean 的属性名相同时,可以使用 byName 的方式,让容器自动将被调用者 Bean 注入给调用者 Bean 。
如图中 id 为 school 的 Bean,正好对应 Student 类中定义的 school 成员变量,在 id 为 myStudent 的 Bean 中直接定义自动注入方式 autowrite=“byName” 即可
byType 方式自动注入
配置文件中被调用者Bean的class属性指定的类,必须要与代码中被调用者Bean类的某域属性同源,即,相同或者具有is-a关系(子类,或者实现类)。同源的被调用者Bean只能有一个,多于一个则会报错,不知道该匹配哪一个。
使用SPEL表达式
SPEL(Spring Expression Language),即 Spring EL 表达式语言。即,在 Spring 配置文件中为 Bean 的属性注入值的时候,可以直接使用 SPEL 表达式计算结果。SPEL表达式以#开头,后加一对大括号。
用法:<bean id="abc" value="#{…}" />。
Person.java
package com.neu.di10; public class Person { private String pname; private int page; // getter and setter // 计算年龄,大于25岁则按照25岁计算 public int computeAge() { return this.page > 25 ? 25 : this.page; } // toString }
Student.java
package com.neu.di10; public class Student { private String name; private int age; // getter and setter // toString }
applicationContext.xml 中的配置
<bean id="myPerson" class="com.neu.di10.Person"> <property name="pname" value="wx"></property> <property name="page" value="#{T(java.lang.Math).random()*50}"></property> </bean> <bean id="myStudent" class="com.neu.di10.Student"> <property name="name" value="#{myPerson.pname}"></property> <property name="age" value="#{myPerson.computeAge()}"></property> <!-- <property name="age" value="#{myPerson.page>25?25:myPerson.page}"></property> --> </bean>
上面仅仅是个例子,具体详细的所有用法可以查看框架解压包下面的 spring-framework-4.2.1.RELEASE\\docs\\spring-framework-reference\\htmlsingle\\index.html 中查找 SPEL 用法
框架包百度云链接 密码是 ycgm
使用内部 Bean 注入
当我们不希望代码直接访问某个 bean,即在代码中通过 getBean 方法获取该 Bean 实例,则可以将该 Bean 的定义放入调用者 bean 定义的内部,例子,
匿名 Bean(虽然无法在代码中通过 getBean() 方法获取,但是可以通过类型自动注入)
<!-- 匿名Bean --> <bean class="com.neu.di11.School"> <property name="sname" value="neu"></property> </bean> <bean id="myStudent" class="com.neu.di11.Student" autowire="byType"> <property name="name" value="js"></property> <property name="age" value="23"></property> </bean>
内部匿名Bean
<!-- 内部匿名bean --> <bean id="myStudent" class="com.neu.di12.Student" autowire="byType"> <property name="name" value="js"></property> <property name="age" value="23"></property> <property name="school"> <bean class="com.neu.di12.School"> <property name="sname" value="neu"></property> </bean> </property> </bean>
使用同类抽象 Bean 注入
当若干的 Bean 实例同属于一个类,这些实例的属性值又有相同值,我们考虑使用抽象 Bean 来避免冗余,简化配置文件
抽象 Bean 是用于让其他的 bean 继承的。这个 bean 不能通过 getBean() 方法来获取,所以应该设置 abstract 属性为 true,其默认值是 false(不设置为抽象 Bean 也能被继承,但一般应该设置为抽象的)
Student 的部分代码
public class Student { private String name; private int age; private String school; private String department;
<!-- 同类抽象Bean --> <bean id="baseStudent" class="com.neu.di13.Student" abstract="true"> <property name="school" value="清华大学"></property> <property name="department" value="计算机学院"></property> </bean> <bean id="student1" parent="baseStudent"> <property name="name" value="JS"></property> <property name="age" value="21"></property> </bean> <bean id="student2" parent="baseStudent"> <property name="name" value="WY"></property> <property name="age" value="22"></property> </bean> <bean id="student3" parent="baseStudent"> <property name="name" value="WX"></property> <property name="age" value="20"></property> </bean>
使用异类抽象 Bean 注入
这种注入应用的情况是若干不同类的对象具有相同的属性,值也相同时。
Student 类的成员变量如之前的同类抽象一样
这是 Teacher 的部分代码(年龄变成了工龄)
public class Teacher { private String name; private int workAge; private String school; private String department;
<!-- 异类抽象Bean --> <bean id="base" abstract="true"> <property name="school" value基于 Spring 注释的 DI 与 xml 配置?[Js-Spring]Spring与IoC(控制反转,Inversion of Control)