Spring学习之——依赖关系和配置细节(一)

这一次的学习主要是对配置的一些特殊属性进行了解和使用。
首先我们要了解的第一个属性就是idref,在前面的学习中我们已经接触到ref这个属性,那么idref和ref这两个属性有什么区别呢,事实上它们两个虽然长得很相似但是却不怎么相干,ref这个属性我们通过前面的学习已经知道,它的作用就是用来引用一个bean的实例用来实现依赖注入的功能,而idref则是用来引用bean的名字的注意是名字而不是实例,一个字符串而已。按照官方文档的说法就是idref是用来将容器中其他bean的id传给<constructor-arg/> 或 <property/> 元素。然后Spring容器可以在工程部署的时校验引用的名字是否存在,其实就是检查bean是不是真的有,降低工程上线运行时的风险。这里面还有一个属性local,配合idref使用更加有效,它可以将校验提前到书写配置的时候,而不必等到工程部署时。其实在我们一般的开发过程中很少用这个属性,但对一些要求比较高的项目而言这个功能还是有一定意义的,毕竟软件开发中问题的及早暴露,能最有效避免掉出现更大麻烦的可能。
我们这里还是先通过一个小程序,来演示一些这个属性的作用。

定义一个TargetBean类,可以没有属性

然后定义一个ClientBean类,如下:

public class ClientBean {
		
	private String tbean;
	
	public String getTbean() {
		return tbean;
	}
	public void setTbean(String tbean) {
		this.tbean = tbean;
	}
}

配置文件bean.xml

<bean id="TargetBean" class="cn.com.spring.injection.bean.TargetBean"/>
	<bean id="ClientBean" class="cn.com.spring.injection.bean.ClientBean">
		<property name="tbean"><idref bean="TargetBean"/></property>
	</bean>


使用Junit测试程序如下:

public class TestUtils extends TestCase {
	private ApplicationContext actx = new FileSystemXmlApplicationContext("bean.xml");
	
	@Test
	public void test(){
		ClientBean exampleBean = (ClientBean)actx.getBean("ClientBean");
		System.out.println(exampleBean.getTbean());
	}
}


运行结果
TargetBean
修改配置文件bean.xml
将TargetBean的配置去掉
然后再次运行,结果失败
再次修改配置文件bean.xml如下

<idref local="TargetBean"/>

发现配置文件报错
这里由于是java工程,就没有部署的步骤,但是通过最后一次的修改可以发现,Spring已经检查到idref引用的bean名字不存在并报错了。

下面我们来学习一下ref这个标签,ref有三个属性,bean,local,parent
我们前面的章节的学习已经接触到ref这个标签了,同时使用了其bean属性,其实很简单bean属性就是要引用的Bean的id名称,下面来说介绍一下它另外两个属性local,parent。
bean的使用范围比较广,使用条件比较弱,几乎在任何情况下都可以使用,属于通吃型的。
local的使用就受点限制,它所引用的bean必须是在当前文件中定义的否则会报错,所以在配置不复杂的情况下最好是用这个,因为它能帮
助你提前校验配置书写是否正确。bean属性则不受这个限制所以Spring容器也就无法事先去校验你书写的配置是否正确。
parent的使用条件比较强,它只能指定位于当前容器的父容器中定义的对象引用,所以这个属性使用就比较少。这里提到了一个父容器的慨念在下面的示例程序中将会有所体现。

下面我改造一下上面的小程序

TargetBean.java

public class TargetBean {
	
	private String name;
	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}
}

ClientBean.java

public class ClientBean {
		
	private TargetBean tbean;
	
	public TargetBean getTbean() {
		return tbean;
	}
	public void setTbean(TargetBean tbean) {
		this.tbean = tbean;
	}
}


配置文件

<bean id="TargetBean" class="cn.com.spring.injection.bean.TargetBean">
		<property name="name" value="targetBean"/>
	</bean>
	<bean id="ClientBean" class="cn.com.spring.injection.bean.ClientBean">
		<property name="tbean"><ref bean="TargetBean"/></property>
	</bean>

测试程序:

	public void test1(){
		ClientBean exampleBean = (ClientBean)actx.getBean("ClientBean");
		System.out.println(exampleBean.getTbean().getName());
	}


运行结果:
targetBean
下面我们修改配置文件,将ref的bean属性修改为local后,再次运行测试程序和上次一样,说明在目前这种配置情况下
这两个属性是几乎没什么区别
下面我们将配置文件分成两个bean1.xml和bean.xml

bean1.xml配置TargetBean

<bean id="TargetBean" class="cn.com.spring.injection.bean.TargetBean">
		<property name="name" value="targetBean"/>
	</bean>


bean.xml配置ClientBean

<import resource="bean1.xml"/>
	<bean id="ClientBean" class="cn.com.spring.injection.bean.ClientBean">
		<property name="tbean"><ref bean="TargetBean"/></property>
	</bean>


执行测试程序发现结果仍然没有问题,但是此时如果将ref的bean改为local,xml文件就会报错,这也验证了local属性的使用条件,所以在同一个配置文件里使用local确实是比bean更好的选择,但是一般在项目开发中配置文件通常是复杂的并且也不只是一个,因此如果对Spring玩的不是很转还是使用bean吧。
下面再来演示一下parent属性,这个玩起来有点麻烦,我们依然是对上面的示例程序进行改造

TargetBean.java不变
ClientBean.java如下

public class ClientBean {
	private TargetBean tb;
	private String flag;
	
	public TargetBean getTb() {
		return tb;
	}
	public void setTb(TargetBean tb) {
		this.tb = tb;
	}
	public String getFlag() {
		return flag;
	}
	public void setFlag(String flag) {
		this.flag = flag;
	}
	
}	


配置文件还是要使用两个我们这里选bean1.xml为父容器,bean.xml为子容器
bean1.xml

<bean id="TargetBean" class="cn.com.spring.injection.bean.TargetBean">
		<property name="name" value="targetBeanChild"/>
	</bean>
	<bean id="TargetBeanParent" class="cn.com.spring.injection.bean.TargetBean">
		<property name="name" value="targetBeanParent"/>
	</bean>


bean.xml

<bean id="TargetBean" class="cn.com.spring.injection.bean.ClientBean">
		<property name="tb"><ref parent="TargetBean"/></property>
		<property name="flag" value="clientBean"/>
	</bean>


测试程序如下:

public class TestUtils extends TestCase {
	private ApplicationContext parent = new FileSystemXmlApplicationContext("bean1.xml");
	private ApplicationContext child = new FileSystemXmlApplicationContext(new String[]{"bean.xml"},parent);
	
	@Test
	public void test1(){
		TargetBean tbean = (TargetBean)parent.getBean("TargetBean");
		TargetBean tbean1 = (TargetBean)child.getBean("TargetBeanParent");
		ClientBean exampleBean = (ClientBean)child.getBean("TargetBean");
		System.out.println(tbean.getName());
		System.out.println(tbean1.getName());
		System.out.println(exampleBean.getTb().getName());
		System.out.println(exampleBean.getFlag());
		System.out.println(tbean.getName());
	}
}


这里注意一下父容器和子容器的设定是通过程序进行的。
运行一下结果如下:
targetBeanChild
targetBeanParent
targetBeanChild
clientBean
targetBeanChild
这里面要注意的就只有两点,一是父容器和子容器是由程序设定的,二是两个配置文件的联系如果使用parent标签bean属性id要和父容器的相同

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值