4、其余引用方式:除了最基本配置方式之外,Spring还提供了另外两种更高级的配置方式,<ref local=””/>和<ref parent=””/>:html
(1)<ref local=””/>配置方式:用于引用经过<bean id=”beanName”>方式中经过id属性指定的Bean,它能利用XML解析器的验证功能在读取配置文件时来验证引用的Bean是否存在。所以若是在当前配置文件中有相互引用的Bean能够采用<ref local>方式从而若是配置错误能在开发调试时就发现错误。前端
若是引用一个在当前配置文件中不存在的Bean将抛出以下异常:java
org.springframework.beans.factory.xml.XmlBeanDefinitionStoreException: Line21 inXML document from class path resource [chapter3/beanInject2.xml] is invalid; nested exception is org.xml.sax.SAXParseException: cvc-id.1: There is no ID/IDREF binding for IDREF 'helloApi'.spring
<ref local>具体配置方式以下:数组
(2)<ref parent=””/>配置方式:用于引用父容器中的Bean,不会引用当前容器中的Bean,固然父容器中的Bean和当前容器的Bean是能够重名的,获取顺序是直接到父容器找。具体配置方式以下:post
接下来让咱们用个例子演示一下<ref local>和<ref parent>的配置过程:测试
首先仍是准备测试类,在此咱们就使用之前写好的HelloApiDecorator和HelloImpl4类;其次进行Bean定义,其中当前容器bean1引用本地的”helloApi”,而”bean2”将引用父容器的”helloApi”,配置以下:this
java代码:spa
<!-- sources/chapter3/parentBeanInject.xml表示父容器配置-->
<!--注意此处可能子容器也定义一个该Bean-->
<bean id="helloApi" class="cn.javass.spring.chapter3.HelloImpl4">
<property name="index" value="1"/>
<property name="message" value="Hello Parent!"/>
</bean>
java代码:
<!-- sources/chapter3/localBeanInject.xml表示当前容器配置-->
<!-- 注意父容器中也定义了id 为 helloApi的Bean -->
<bean id="helloApi" class="cn.javass.spring.chapter3.HelloImpl4">
<property name="index" value="1"/>
<property name="message" value="Hello Local!"/>
</bean>
<!-- 经过local注入 -->
<bean id="bean1" class="cn.javass.spring.chapter3.bean.HelloApiDecorator">
<constructor-arg index="0"><ref local="helloApi"/></constructor-arg>
</bean>
<!-- 经过parent注入 -->
<bean id="bean2" class="cn.javass.spring.chapter3.bean.HelloApiDecorator">
<property name="helloApi"><ref parent="helloApi"/></property>
</bean>
(3)写测试类测试一下吧,具体代码片断以下:
java代码:
public void testLocalAndparentBeanInject() {
//初始化父容器
ApplicationContext parentBeanContext =
new ClassPathXmlApplicationContext("chapter3/parentBeanInject.xml");
//初始化当前容器
ApplicationContext beanContext = new ClassPathXmlApplicationContext(
new String[] {"chapter3/localBeanInject.xml"}, parentBeanContext);
HelloApi bean1 = beanContext.getBean("bean1", HelloApi.class);
bean1.sayHello();//该Bean引用local bean
HelloApi bean2 = beanContext.getBean("bean2", HelloApi.class);
bean2.sayHello();//该Bean引用parent bean
}
“bean1”将输出“Hello Local!”表示引用当前容器的Bean,”bean2”将输出“Hello Paren!”,表示引用父容器的Bean,如配置有问题请参考cn.javass.spring.chapter3.DependencyInjectTest中的testLocalAndparentBeanInject测试方法。
内部Bean就是在<property>或<constructor-arg>内经过<bean>标签订义的Bean,该Bean无论是否指定id或name,该Bean都会有惟一的匿名标识符,并且不能指定别名,该内部Bean对其余外部Bean不可见,具体配置以下:
(1)让咱们写个例子测试一下吧,具体配置文件以下:
java代码:
<bean id="bean" class="cn.javass.spring.chapter3.bean.HelloApiDecorator">
<property name="helloApi">
<bean id="helloApi" class="cn.javass.spring.chapter2.helloworld.HelloImpl"/>
</property>
</bean>
(2)测试代码(cn.javass.spring.chapter3.DependencyInjectTest.testInnerBeanInject):
java代码:
public void testInnerBeanInject() {
ApplicationContext context =
new ClassPathXmlApplicationContext("chapter3/innerBeanInject.xml");
HelloApi bean = context.getBean("bean", HelloApi.class);
bean.sayHello();
}
Spring经过<value>标签或value属性注入常量值,全部注入的数据都是字符串,那如何注入null值呢?经过“null”值吗?固然不是由于若是注入“null”则认为是字符串。Spring经过<null/>标签注入null值。便可以采用以下配置方式:
所谓对象图导航是指相似a.b.c这种点缀访问形式的访问或修改值。Spring支持对象图导航方式依赖注入。对象图导航依赖注入有一个限制就是好比a.b.c对象导航图注入中a和b必须为非null值才能注入c,不然将抛出空指针异常。
Spring不只支持对象的导航,还支持数组、列表、字典、Properties数据类型的导航,对Set数据类型没法支持,由于没法导航。
数组和列表数据类型能够用array[0]、list[1]导航,注意”[]”里的必须是数字,由于是按照索引进行导航,对于数组类型注意不要数组越界错误。
字典Map数据类型可使用map[1]、map[str]进行导航,其中“[]”里的是基本类型,没法放置引用类型。
让咱们来练习一下吧。首先准备测试类,在此咱们须要三个测试类,以便实现对象图导航功能演示:
NavigationC类用于打印测试代码,从而观察配置是否正确;具体类以下所示:
java代码:
package cn.javass.spring.chapter3.bean;
public class NavigationC {
public void sayNavigation() {
System.out.println("===navigation c");
}
}
NavigationB类,包含对象和列表、Properties、数组字典数据类型导航,并且这些复合数据类型保存的条目都是对象,正好练习一下如何往复合数据类型中注入对象依赖。具体类以下所示:
java代码:
package cn.javass.spring.chapter3.bean;
import java.util.List;
import java.util.Map;
import java.util.Properties;
public class NavigationB {
private NavigationC navigationC;
private List<NavigationC> list;
private Properties properties;
private NavigationC[] array = new NavigationC[1];
private Map<String, NavigationC> map;
//因为setter和getter方法占用太多空间,故省略,你们本身实现吧
}
NavigationA类是咱们的前端类,经过对它的导航进行注入值,具体代码以下:
java代码:
package cn.javass.spring.chapter3.bean;
public class NavigationA {
private NavigationB navigationB;
public void setNavigationB(NavigationB navigationB) {
this.navigationB = navigationB;
}
public NavigationB getNavigationB() {
return navigationB;
}
}
接下来该进行Bean定义配置(resources/chapter3/navigationBeanInject.xml)了,首先让咱们配置一下须要被导航的数据,NavigationC和NavigationB类,其中配置NavigationB时注意要确保好比array字段不为空值,这就须要或者在代码中赋值如“NavigationC[] array = new NavigationC[1];”,或者经过配置文件注入如“<list></list>”注入一个不包含条目的列表。具体配置以下:
java代码:
<bean id="c" class="cn.javass.spring.chapter3.bean.NavigationC"/>
<bean id="b" class="cn.javass.spring.chapter3.bean.NavigationB">
<property name="list"><list></list></property>
<property name="map"><map></map></property>
<property name="properties"><props></props></property>
</bean>
配置完须要被导航的Bean定义了,该来配置NavigationA导航Bean了,在此须要注意,因为“navigationB”属性为空值,在此须要首先注入“navigationB”值;还有对于数组导航不能越界不然报错;具体配置以下:
java代码:
<bean id="a" class="cn.javass.spring.chapter3.bean.NavigationA">
<!-- 首先注入navigatiionB 确保它非空 -->
<property name="navigationB" ref="b"/>
<!-- 对象图导航注入 -->
<property name="navigationB.navigationC" ref="c"/>
<!-- 注入列表数据类型数据 -->
<property name="navigationB.list[0]" ref="c"/>
<!-- 注入map类型数据 -->
<property name="navigationB.map[key]" ref="c"/>
<!-- 注入properties类型数据 -->
<property name="navigationB.properties[0]" ref="c"/>
<!-- 注入properties类型数据 -->
<property name="navigationB.properties[1]" ref="c"/>
<!-- 注入数组类型数据 ,注意不要越界-->
<property name="navigationB.array[0]" ref="c"/>
</bean>
配置完毕,具体测试代码在cn.javass.spring.chapter3. DependencyInjectTest,让咱们看下测试代码吧:
java代码:
//对象图导航
public void testNavigationBeanInject() {
ApplicationContext context =
new ClassPathXmlApplicationContext("chapter3/navigationBeanInject.xml");
NavigationA navigationA = context.getBean("a", NavigationA.class);
navigationA.getNavigationB().getNavigationC().sayNavigation();
navigationA.getNavigationB().getList().get(0).sayNavigation();
navigationA.getNavigationB().getMap().get("key").sayNavigation();
navigationA.getNavigationB().getArray()[0].sayNavigation();
((NavigationC)navigationA.getNavigationB().getProperties().get("1"))
.sayNavigation();
}
测试完毕,应该输出5个“===navigation c”,是否是很简单,注意这种方式是不推荐使用的,了解一下就够了,最好使用3.1.5一节使用的配置方式。
让咱们来总结一下依赖注入配置及简写形式,其实咱们已经在以上部分穿插着进行简化配置了:
1、构造器注入:
1)常量值
简写:<constructor-arg index="0" value="常量"/>
全写:<constructor-arg index="0"><value>常量</value></constructor-arg>
2)引用
简写:<constructor-arg index="0" ref="引用"/>
全写:<constructor-arg index="0"><ref bean="引用"/></constructor-arg>
2、setter注入:
1)常量值
简写:<property name="message" value="常量"/>
全写:<property name="message"><value>常量</value></ property>
2)引用
简写:<property name="message" ref="引用"/>
全写:<property name="message"><ref bean="引用"/></ property>
3)数组:<array>没有简写形式
4)列表:<list>没有简写形式
5)集合:<set>没有简写形式
6)字典
简写:<map>
<entry key="键常量" value="值常量"/>
<entry key-ref="键引用" value-ref="值引用"/>
</map>
全写:<map>
<entry><key><value>键常量</value></key><value>值常量</value></entry>
<entry><key><ref bean="键引用"/></key><ref bean="值引用"/></entry>
</map>
7)Properties:没有简写形式
3、使用p命名空间简化setter注入:
使用p命名空间来简化setter注入,具体使用以下:
java代码:
<?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"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<bean id="bean1" class="java.lang.String">
<constructor-arg index="0" value="test"/>
</bean>
<bean id="idrefBean1" class="cn.javass.spring.chapter3.bean.IdRefTestBean"
p:id="value"/>
<bean id="idrefBean2" class="cn.javass.spring.chapter3.bean.IdRefTestBean"
p:id-ref="bean1"/>
</beans>
xmlns:p="http://www.springframework.org/schema/p" :首先指定p命名空间;
<bean id="……" class="……" p:id="value"/> :常量setter注入方式,其等价于<property name="id" value="value"/>;
<bean id="……" class="……" p:id-ref="bean1"/> :引用setter注入方式,其等价于<property name="id" ref="bean1"/>。
原创内容,转载请注明【http://sishuok.com/forum/posts/list/2447.html】