Spring容器的属性配置详解的六个专题

在spring IOC容器的配置文件applicationContext.xml里,有一些配置细节值得一提。咱们将一些问题归结为如下几个专题。java

专题一:字面值问题

配置的bean节点中的值,咱们提出一个概念——字面值。mysql

字面值:可用字符串表示的值.spring

字面值能够经过 <value> 元素标签或 value 属性进行注入。sql

基本数据类型及其封装类、String 等类型均可以采起字面值注入的方式数据库

若字面值中包含特殊字符,可使用 <![CDATA[]]> 把字面值包裹起来。数组

例如:(本文出自:http://my.oschina.net/happyBKs/blog/478074)app

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

	<bean id="car_value_id" class="com.happBKs.spring.iocaop.beans.Car">
		<constructor-arg name="price1">
			<value>200000</value>
		</constructor-arg>
		<constructor-arg name="name1">
		<value><![CDATA[<BM>]]></value>
		</constructor-arg>
	</bean>
	<!-- 若是字面值包括特殊字符,能够用<![CDATA[ ]]>括起来 -->

</beans>

Car定义:eclipse

package com.happBKs.spring.iocaop.beans;

public class Car {
	String name;
	double price;
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public double getPrice() {
		return price;
	}
	public void setPrice(double price) {
		this.price = price;
	}
	public Car() {
		super();
	}
	public Car(String name1, double price1) {
		super();
		this.name = name1;
		this.price = price1;
	}
	@Override
	public String toString() {
		return "Car [name=" + name + ", price=" + price + "]";
	}
}

测试代码:ide

@Test
	public void test8()
	{
		//建立spring IOC容器对象。ClassPathXmlApplicationContext表示配置文件在类路径下,它是接口ApplicationContext的一个实现类。
		ApplicationContext ctx=new ClassPathXmlApplicationContext("applicationContext.xml");
		//从IOC容器中获取Bean实例
		Car cBean=(Car)ctx.getBean("car_value_id");
		//调用对象方法
		System.out.println(cBean);
	}

结果输出:工具

Car [name=<BM>, price=200000.0]

在上例中,属性值可使用value子节点进行配置。

专题二:bean的属性是另外一个bean

在bean类的定义中每每存在这样的状况, 另类的某个属性是另外一个bean对象。这样的状况,要使得容器可以在自动生成相应对象,应该怎么作的呢。

首先咱们定义一个Person类,每一个Person有一个Car类型属性。

package com.happBKs.spring.iocaop.beans;

public class Person {

	String username;
	Car userCar;
	
	public String getUsername() {
		return username;
	}
	public void setUsername(String username) {
		this.username = username;
	}
	public Car getUserCar() {
		return userCar;
	}
	public void setUserCar(Car userCar) {
		this.userCar = userCar;
	}
	public Person(String username, Car userCar) {
		super();
		this.username = username;
		this.userCar = userCar;
	}
	public Person() {
		super();
	}
	@Override
	public String toString() {
		return "Person [username=" + username + ", userCar=" + userCar + "]";
	}
	
	
}

容器配制文件:咱们使用property的ref属性来引用属性类型,即创建bean之间的引用关系。

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

	<bean id="car_id" class="com.happBKs.spring.iocaop.beans.Car">
		<constructor-arg value="BM"></constructor-arg>
		<constructor-arg value="500000"></constructor-arg>
	</bean>

	<bean id="caruser" class="com.happBKs.spring.iocaop.beans.Person">
		<property name="username" value="HappyBKs"></property>
		<property name="userCar" ref="car_id"></property>
	</bean>

</beans>

测试代码:

@Test
	public void test9()
	{
		//建立spring IOC容器对象。ClassPathXmlApplicationContext表示配置文件在类路径下,它是接口ApplicationContext的一个实现类。
		ApplicationContext ctx=new ClassPathXmlApplicationContext("applicationContext.xml");
		//从IOC容器中获取Bean实例
		Person pBean=(Person)ctx.getBean("caruser");
		//调用对象方法
		System.out.println(pBean);
	}

运行结果:

Person [username=HappyBKs, userCar=Car [name=BM, price=500000.0]]

组成应用程序的 Bean 常常须要相互协做以完成应用程序的功能. 要使 Bean 可以相互访问, 就必须在 Bean 配置文件中指定对 Bean 的引用

在 Bean 的配置文件中, 能够经过 <ref> 元素或 ref 属性为 Bean 的属性或构造器参数指定对 Bean 的引用.

也就是说,刚才的容器配制还能够写成:

<bean id="caruser" class="com.happBKs.spring.iocaop.beans.Person">
		<property name="username" value="HappyBKs"></property>
		<property name="userCar">
		    <ref bean="car_id"/>
		</property>
	</bean>

也能够在属性或构造器里包含 Bean 的声明, 这样的 Bean 称为内部 Bean。

如,上面的例子能够写成另外一种内部bean的形式。这种内部bean的形式,不用再有id属性,由于它不可能被外部引用。

<bean id="caruserB" class="com.happBKs.spring.iocaop.beans.Person">
		<property name="username" value="HappyBKs"></property>
		<property name="userCar">
			<bean class="com.happBKs.spring.iocaop.beans.Car">
				<constructor-arg value="450000" index="1"></constructor-arg>
				<constructor-arg value="Volvo" index="0"></constructor-arg>
			</bean>
		</property>
	</bean>

测试代码:

@Test
	public void test10()
	{
		//建立spring IOC容器对象。ClassPathXmlApplicationContext表示配置文件在类路径下,它是接口ApplicationContext的一个实现类。
		ApplicationContext ctx=new ClassPathXmlApplicationContext("applicationContext.xml");
		//从IOC容器中获取Bean实例
		Person pBean=(Person)ctx.getBean("caruserB");
		//调用对象方法
		System.out.println(pBean);
	}

输出结果:

Person [username=HappyBKs, userCar=Car [name=Volvo, price=450000.0]]

当 Bean 实例仅仅给一个特定的属性使用时, 能够将其声明为内部 Bean. 内部 Bean 声明直接包含在 <property> 或 <constructor-arg> 元素里, 不须要设置任何 id 或 name 属性。

内部 Bean 不能使用在任何其余地方。

专题三:特殊注入参数:null 值

咱们有时须要将bean的某个属性设置为null,这在spring容器的配置文件里面怎么描述呢?

这就要用到一个特殊的标签<null/>

<bean id="caruserB" class="com.happBKs.spring.iocaop.beans.Person">
		<property name="username" value="HappyBKs"></property>
		<property name="userCar">
			<bean class="com.happBKs.spring.iocaop.beans.Car">
				<constructor-arg value="450000" index="1"></constructor-arg>
				<constructor-arg index="0"><null/></constructor-arg>
			</bean>
		</property>
	</bean>

运行刚才的test10方法,输出结果:

Person [username=HappyBKs, userCar=Car [name=null, price=450000.0]]

专题四:特殊注入参数:级联属性

另外一种bean中比较特殊的赋值是级联属性。什么叫级联属性呢?其实你一看就明白了,就是对象的属性子对象的属性。

配置文件中配置bean的属性时,property标签不只能直接配置该bean对应的类自身的属性,并且还能够直接配置该类的属性对象向的属性,即级联属性。

<bean id="caruserC" class="com.happBKs.spring.iocaop.beans.Person">
		<property name="username" value="HappyBKs"/>
		<property name="userCar" ref="car_id"/>
		<property name="userCar.price" value="350000"/>
	</bean>

测试代码:

@Test
	public void test11()
	{
		//建立spring IOC容器对象。ClassPathXmlApplicationContext表示配置文件在类路径下,它是接口ApplicationContext的一个实现类。
		ApplicationContext ctx=new ClassPathXmlApplicationContext("applicationContext.xml");
		//从IOC容器中获取Bean实例
		Person pBean=(Person)ctx.getBean("caruserC");
		//调用对象方法
		System.out.println(pBean);
	}

输出结果:

Person [username=HappyBKs, userCar=Car [name=BM, price=350000.0]]

固然,若是配置的bean中前面用构造器注入,也能够同时使用级联属性赋值。

<bean id="caruserC" class="com.happBKs.spring.iocaop.beans.Person">
		<constructor-arg value="BM"></constructor-arg>
		<constructor-arg value="500000"></constructor-arg>
		<property name="userCar.price" value="350000"/>
	</bean>

可是有一个十分须要注意的问题:这里的级联属性被赋值的前提是级联属性所属的对象属性已经被属性注入或构造器注入赋值,不然会报异常。这一点与struts2不一样,struts2这种状况会为级联属性所属对象自动生成实例,而spring不行。

专题五:集合属性

在类的属性中每每又一些属性是集合性质的类型,如List、Set、Map等,或者是一个数组类型。

在Spring中,这样的类在容器中应该如何配置呢?

在 Spring中能够经过一组内置的 xml 标签(例如: <list>, <set> 或 <map>) 来配置集合属性.

配置 java.util.List 类型的属性, 须要指定 <list> 标签, 在标签里包含一些元素. 这些标签能够经过 <value> 指定简单的常量值, 经过 <ref> 指定对其余 Bean 的引用. 经过<bean> 指定内置 Bean 定义. 经过 <null/> 指定空元素. 甚至能够内嵌其余集合。

数组的定义和 List 同样, 都使用 <list>。

配置 java.util.Set 须要使用 <set> 标签, 定义元素的方法与 List 同样。

List集合属性

那咱们如今来看一个List的例子。

咱们定义一个RichPerson类:它有一个userCars属性是List类型。

package com.happBKs.spring.iocaop.beans;

import java.util.List;

public class RichPerson {

	String username;
	List<Car> userCars;
	public String getUsername() {
		return username;
	}
	public void setUsername(String username) {
		this.username = username;
	}
	public List<Car> getUserCars() {
		return userCars;
	}
	public void setUserCars(List<Car> userCars) {
		this.userCars = userCars;
	}
	public RichPerson(String username, List<Car> userCars) {
		super();
		this.username = username;
		this.userCars = userCars;
	}
	public RichPerson() {
		super();
	}
	@Override
	public String toString() {
		return "RichPerson [username=" + username + ", userCars=" + userCars
				+ "]";
	}
}

在applicationContext.xml中,配置以下信息:

咱们将对应userCars的property标签里加入<list>标签

在<list>标签里咱们逐个加入bean。

加入方法有多种,这里使用了两种:

一种是ref,引用外部的bean。如前三个单元的bean。

另外一种是本身定义内部bean,与前面介绍的内部bean相似。

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

	<bean id="privateCar1" class="com.happBKs.spring.iocaop.beans.Car">
		<constructor-arg value="BM"></constructor-arg>
		<constructor-arg value="800000"></constructor-arg>
	</bean>
	<bean id="privateCar2" class="com.happBKs.spring.iocaop.beans.Car">
		<constructor-arg value="Volvo"></constructor-arg>
		<constructor-arg value="500000"></constructor-arg>
	</bean>

	<bean id="richPerson1" class="com.happBKs.spring.iocaop.beans.RichPerson">
		<property name="username" value="HappyBKs" />
		<property name="userCars">
			<list>
				<ref bean="privateCar1" />
				<ref bean="privateCar1" />
				<ref bean="privateCar2" />
				<bean id="privateCarSecret" class="com.happBKs.spring.iocaop.beans.Car">
					<constructor-arg value="Tank"></constructor-arg>
					<constructor-arg value="100000000000"></constructor-arg>
				</bean>
			</list>
		</property>
	</bean>
</beans>

测试方法:

@Test
	public void test12()
	{
		//建立spring IOC容器对象。ClassPathXmlApplicationContext表示配置文件在类路径下,它是接口ApplicationContext的一个实现类。
		ApplicationContext ctx=new ClassPathXmlApplicationContext("applicationContext.xml");
		//从IOC容器中获取Bean实例
		RichPerson pBean=(RichPerson)ctx.getBean("richPerson1");
		//调用对象方法
		System.out.println(pBean);
	}

输出结果:

RichPerson [username=HappyBKs, userCars=[Car [name=BM, price=800000.0], Car [name=BM, price=800000.0], Car [name=Volvo, price=500000.0], Car [name=Tank, price=1.0E11]]]

Map的集合属性

咱们再看一个Map的集合属性的例子。

package com.happBKs.spring.iocaop.beans;

import java.util.Map;

public class RichMapPerson {

	String username;
	Map<String,Car> userCars;
	public String getUsername() {
		return username;
	}
	public void setUsername(String username) {
		this.username = username;
	}
	public Map<String, Car> getUserCars() {
		return userCars;
	}
	public void setUserCars(Map<String, Car> userCars) {
		this.userCars = userCars;
	}
	public RichMapPerson(String username, Map<String, Car> userCars) {
		super();
		this.username = username;
		this.userCars = userCars;
	}
	public RichMapPerson() {
		super();
	}
	@Override
	public String toString() {
		return "RichMapPerson [username=" + username + ", userCars=" + userCars
				+ "]";
	}
		
}

配置容器:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

	<bean id="privateCar1" class="com.happBKs.spring.iocaop.beans.Car">
		<constructor-arg value="BM"></constructor-arg>
		<constructor-arg value="800000"></constructor-arg>
	</bean>
	<bean id="privateCar2" class="com.happBKs.spring.iocaop.beans.Car">
		<constructor-arg value="Volvo"></constructor-arg>
		<constructor-arg value="500000"></constructor-arg>
	</bean>

	<bean id="richMapPerson1" class="com.happBKs.spring.iocaop.beans.RichMapPerson">
		<property name="username" value="HappyBKs" />
		<property name="userCars">
			<map>
				<entry key="WorkCar" value-ref="privateCar1"></entry>
				<entry key="ShoppingCar" value-ref="privateCar2"></entry>
			</map>
		</property>
	</bean>
</beans>

不过很惋惜的是entry貌似不支持内部bean的定义,即一下状况是报错的,提示不支持此处以bean开头。

<bean id="richMapPerson1" class="com.happBKs.spring.iocaop.beans.RichMapPerson">
		<property name="username" value="HappyBKs" />
		<property name="userCars">
			<map>
				<entry key="WorkCar" value-ref="privateCar1"></entry>
				<entry key="ShoppingCar" value-ref="privateCar2"></entry>
				<entry key="OXOXCar">
					<value type="com.happBKs.spring.iocaop.beans.Car">
					
							<property name="name" value="taxi"></property>
							<property name="price" value="50000"></property>
					</value>
				</entry>
			</map>
		</property>
	</bean>

回到刚才,测试方法:

@Test
	public void test13()
	{
		//建立spring IOC容器对象。ClassPathXmlApplicationContext表示配置文件在类路径下,它是接口ApplicationContext的一个实现类。
		ApplicationContext ctx=new ClassPathXmlApplicationContext("applicationContext.xml");
		//从IOC容器中获取Bean实例
		RichMapPerson pBean=(RichMapPerson)ctx.getBean("richMapPerson1");
		//调用对象方法
		System.out.println(pBean);
	}

运行结果:

RichMapPerson [username=HappyBKs, userCars={WorkCar=Car [name=BM, price=800000.0], ShoppingCar=Car [name=Volvo, price=500000.0]}]

Properties类的属性

Properties类型其实能够算Map类型的子类型:它是HashTable类型的子类噢! 输入图片说明

如今咱们来定义一个bean,用来记录数据库配置信息:

package com.happBKs.spring.iocaop.beans;

import java.util.Properties;

public class DataSourceBean {
	
	Properties propertiesInfo;

	public Properties getPropertiesInfo() {
		return propertiesInfo;
	}

	public void setPropertiesInfo(Properties propertiesInfo) {
		this.propertiesInfo = propertiesInfo;
	}

	public DataSourceBean(Properties propertiesInfo) {
		super();
		this.propertiesInfo = propertiesInfo;
	}

	public DataSourceBean() {
		super();
	}

	@Override
	public String toString() {
		return "DataSourceBean [propertiesInfo=" + propertiesInfo + "]";
	}

}

spring IOC容器配置:

<bean id="DataSourceId" class="com.happBKs.spring.iocaop.beans.DataSourceBean">
		<property name="propertiesInfo">
			<props>
				<prop key="user">root</prop>
				<prop key="password"></prop>
				<prop key="jdbcUrl">jdbc:mysql:///test</prop>
				<prop key="driverClass">com.mysql.jdbc.Driver</prop>
			</props>
		</property>
	</bean>

测试方法:

@Test
	public void test14()
	{
		//建立spring IOC容器对象。ClassPathXmlApplicationContext表示配置文件在类路径下,它是接口ApplicationContext的一个实现类。
		ApplicationContext ctx=new ClassPathXmlApplicationContext("applicationContext.xml");
		//从IOC容器中获取Bean实例
		DataSourceBean dBean=(DataSourceBean)ctx.getBean("DataSourceId");
		//调用对象方法
		System.out.println(dBean);
	}

输出结果:

DataSourceBean [propertiesInfo={driverClass=com.mysql.jdbc.Driver, user=root, password=, jdbcUrl=jdbc:mysql:///test}]

集合类型能够外置(使用 utility scheme 定义集合)

前面提到的这些集合属性在spring ioc容器配置时,都是能够做为外部单元存在的,就像bean存在外部bean和内部bean同样。

使用基本的集合标签订义集合时, 不能将集合做为独立的 Bean 定义, 致使其余 Bean 没法引用该集合, 因此没法在不一样 Bean 之间共享集合.

可使用 util schema 里的集合标签订义独立的集合 Bean. 须要注意的是, 必须在 <beans> 根元素里添加 util schema 定义。

咱们以List为例,看下面例子:

首先咱们须要给applicationContext.xml加入一个命名空间:

能够用STS、eclipse的编辑工具选择下面的NameSpace编辑视图,直接勾选util命名空间。

输入图片说明

配置文件Source以下:

<?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:util="http://www.springframework.org/schema/util"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.1.xsd">

	<bean id="privateCar1" class="com.happBKs.spring.iocaop.beans.Car">
		<constructor-arg value="BM"></constructor-arg>
		<constructor-arg value="800000"></constructor-arg>
	</bean>
	<bean id="privateCar2" class="com.happBKs.spring.iocaop.beans.Car">
		<constructor-arg value="Volvo"></constructor-arg>
		<constructor-arg value="500000"></constructor-arg>
	</bean>


	<util:list id="carsList">
		<ref bean="privateCar1" />
		<ref bean="privateCar2" />
		<bean class="com.happBKs.spring.iocaop.beans.Car">
			<constructor-arg value="Audi"></constructor-arg>
			<constructor-arg value="700000"></constructor-arg>
		</bean>
	</util:list>
	
	<bean id="richPerson2" class="com.happBKs.spring.iocaop.beans.RichPerson">
	<property name="username" value="happyBKs"/>
	<property name="userCars" ref="carsList"></property>
	</bean>
	
</beans>

除了util:list标签,spring-util-4.1命名空间中还有其余集合标签:

输入图片说明

输出结果:

RichPerson [username=happyBKs, userCars=[Car [name=BM, price=800000.0], Car [name=Volvo, price=500000.0], Car [name=Audi, price=700000.0]]]

专题六:方便的p命名空间

为了简化 XML 文件的配置,愈来愈多的 XML 文件采用属性而非子元素配置信息。

Spring 从 2.5 版本开始引入了一个新的 p 命名空间,能够经过 <bean> 元素属性的方式配置 Bean 的属性。

使用 p 命名空间后,基于 XML 的配置方式将进一步简化

首先,咱们须要按照以前的方法导入命名空间。 输入图片说明

以后,咱们在最后加入一个bean,id为richPerson3,你发现依赖于p命名空间,如今这个bean只有一行了,十分简洁。

<?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:util="http://www.springframework.org/schema/util"
	xmlns:p="http://www.springframework.org/schema/p"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.1.xsd">

	<bean id="privateCar1" class="com.happBKs.spring.iocaop.beans.Car">
		<constructor-arg value="BM"></constructor-arg>
		<constructor-arg value="800000"></constructor-arg>
	</bean>
	<bean id="privateCar2" class="com.happBKs.spring.iocaop.beans.Car">
		<constructor-arg value="Volvo"></constructor-arg>
		<constructor-arg value="500000"></constructor-arg>
	</bean>

	<util:list id="carsList">
		<ref bean="privateCar1" />
		<ref bean="privateCar2" />
		<bean class="com.happBKs.spring.iocaop.beans.Car">
			<constructor-arg value="Audi"></constructor-arg>
			<constructor-arg value="700000"></constructor-arg>
		</bean>
	</util:list>
	

	<bean id="richPerson3" class="com.happBKs.spring.iocaop.beans.RichPerson" p:username="happyBKs" p:userCars-ref="carsList"/>

	
	
</beans>

测试方法:

@Test
	public void test16()
	{
		//建立spring IOC容器对象。ClassPathXmlApplicationContext表示配置文件在类路径下,它是接口ApplicationContext的一个实现类。
		ApplicationContext ctx=new ClassPathXmlApplicationContext("applicationContext.xml");
		//从IOC容器中获取Bean实例
		RichPerson pBean=(RichPerson)ctx.getBean("richPerson3");
		//调用对象方法
		System.out.println(pBean);
	}

运行结果:

RichPerson [username=happyBKs, userCars=[Car [name=BM, price=800000.0], Car [name=Volvo, price=500000.0], Car [name=Audi, price=700000.0]]]

连接

https://my.oschina.net/happyBKs/blog/478074

相关文章
相关标签/搜索