3.装配bean(二)

        本章主要继续介绍spring基于XML装配bean的知识,主要介绍spring对属性的注入。

 设值注入简单值和引用其他bean:

package org.robbie.test.spring.beans;

public interface Instrument {
	void play();
}

 

package org.robbie.test.spring.beans;

public class Flute implements Instrument {

	@Override
	public void play() {
		System.out.println("play flute");
	}

}
package org.robbie.test.spring.beans;

import org.robbie.test.spring.exception.PerformerException;
import org.robbie.test.spring.inf.Performer;

public class Instrumentalist implements Performer {

	private String song;

	private Instrument instrument;

	public Instrumentalist() {
	}

	@Override
	public void perform() throws PerformerException {
		
	}

	public String getSong() {
		return song;
	}

	public void setSong(String song) {
		this.song = song;
	}

	public Instrument getInstrument() {
		return instrument;
	}

	public void setInstrument(Instrument instrument) {
		this.instrument = instrument;
	}

}
<?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-3.0.xsd">

	<bean id="instrumentalist" class="org.robbie.test.spring.beans.Instrumentalist">
		<property name="instrument" ref="flute"></property>
		<property name="song" value="god is a girl"></property>
	</bean>
	<bean id="flute" class="org.robbie.test.spring.beans.Flute"></bean>
</beans>

 

注入内部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-3.0.xsd">

	<bean id="instrumentalist" class="org.robbie.test.spring.beans.Instrumentalist">
		<property name="instrument">
			<bean class="org.robbie.test.spring.beans.Flute"></bean>
		</property>
		<property name="song" value="god is a girl"></property>
	</bean>
</beans>

 内部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-3.0.xsd">

	<bean id="instrumentalist" class="org.robbie.test.spring.beans.Instrumentalist">
		<constructor-arg>
			<bean class="org.robbie.test.spring.beans.Flute"></bean>
		</constructor-arg>
		<property name="song" value="god is a girl"></property>
	</bean>
</beans>

从上面的例子可以看出, 内部bean适用于一次性注入,不能被复用,也没有ID(可以给ID,但是没有用处),并且影响XML的可读性,这样的配置方式比较少见,在项目中谨慎适用。

适用命名空间装配属性

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:p="http://www.springframework.org/schema/p"
	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-3.0.xsd">

	<bean id="instrumentalist" class="org.robbie.test.spring.beans.Instrumentalist"
		p:song="god is a girl" p:instrument-ref="flute">
	</bean>
	<bean id="flute" class="org.robbie.test.spring.beans.Flute"></bean>
</beans>

 上面的例子增加了一段命名空间配置:

xmlns:p="http://www.springframework.org/schema/p"

装配集合属性

集合元素 用途
<list> 装配list类型的值,允许重复
<set> 装配set类型的值,不允许重复
<map> 装配map类型的值,名称和值可以为任意类型
<props> 装配properties类型的值,名称和值必须为string类型

装配List,Set和Array

package org.robbie.test.spring.beans;

import java.util.Collection;

public class Band {

	private Collection<Instrument> instruments;

	public Collection<Instrument> getInstruments() {
		return instruments;
	}

	public void setInstruments(Collection<Instrument> instruments) {
		this.instruments = instruments;
	}
}

 

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:p="http://www.springframework.org/schema/p"
	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-3.0.xsd">
           
	<bean id="flute" class="org.robbie.test.spring.beans.Flute"></bean>
	<bean id="guita" class="org.robbie.test.spring.beans.Guita"></bean>
	<bean id="piano" class="org.robbie.test.spring.beans.Piano"></bean>
	<bean id="band" class="org.robbie.test.spring.beans.Band">
		<property name="instruments">
			<list>
				<ref bean="flute" />
				<ref bean="guita" />
				<ref bean="piano" />
			</list>
		</property>
	</bean>
</beans>

 如果属性不为集合,而是数组,例如Instrument[] instruments也同样适用以上配置。

以下为Set集合装配

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:p="http://www.springframework.org/schema/p"
	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-3.0.xsd">
           
	<bean id="flute" class="org.robbie.test.spring.beans.Flute"></bean>
	<bean id="guita" class="org.robbie.test.spring.beans.Guita"></bean>
	<bean id="piano" class="org.robbie.test.spring.beans.Piano"></bean>
	<bean id="band" class="org.robbie.test.spring.beans.Band">
		<property name="instruments">
			<set>
				<ref bean="flute" />
				<ref bean="guita" />
				<ref bean="piano" />
			</set>
		</property>
	</bean>
</beans>

Map集合装配

package org.robbie.test.spring.beans;

import java.util.Map;

public class Band {

	private Map<String, Instrument> instruments;

	public Map<String, Instrument> getInstruments() {
		return instruments;
	}

	public void setInstruments(Map<String, Instrument> instruments) {
		this.instruments = instruments;
	}

}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:p="http://www.springframework.org/schema/p"
	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-3.0.xsd">
           
	<bean id="flute" class="org.robbie.test.spring.beans.Flute"></bean>
	<bean id="guita" class="org.robbie.test.spring.beans.Guita"></bean>
	<bean id="piano" class="org.robbie.test.spring.beans.Piano"></bean>
	<bean id="band" class="org.robbie.test.spring.beans.Band">
		<property name="instruments">
			<map>
				<entry key="flute" value-ref="flute"></entry>
				<entry key="guita" value-ref="guita"></entry>
				<entry key="piano" value-ref="piano"></entry>
			</map>
		</property>
	</bean>
</beans>
属性 用途
key 指定map中entry的键为String
key-ref 指定map中entry的键为spring上下文中其他bean的引用
value 指定map中entry的值为String
value-ref 指定map中entry的值为spring上下文中其他bean的引用

装配properties集合

package org.robbie.test.spring.beans;

import java.util.Properties;

public class Band {

	private Properties instruments;

	public Properties getInstruments() {
		return instruments;
	}

	public void setInstruments(Properties instruments) {
		this.instruments = instruments;
	}

}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:p="http://www.springframework.org/schema/p"
	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-3.0.xsd">
           
	<bean id="band" class="org.robbie.test.spring.beans.Band">
		<property name="instruments">
			<props>
				<prop key="guita" >guita</prop>
				<prop key="piano" >piano</prop>
				<prop key="flute" >flute</prop>
			</props>
		</property>
	</bean>
</beans>

装配空值:

在某些特定情况下,如果全局变量给定了一个默认的值,但是在创建对象的时候,又想为整个变量设置为空时,可以采用spring的空值注入。

<property name="instruments"><null /></property>

使用表达式装配:

        之前所有的基于XML的装配都成为静态装配,如果在某些时候需要在运行期动态的对spring bean进行装配的话需要用到springEL(Spring Expression Language),springEL是用一种表达式,通过计算在运行期进行bean的装配,包括对属性和构造参数的装配等,通过使用springEL可以达到难以想象的动态装配效果。

SpringEL拥有很多特性,包括:

使用bean的ID来引用bean
调用方法和访问对象的属性
对值进行算术、关系、逻辑运算
正则表达式匹配
集合操作

SpringEL中的字面值:

整形:

<property name="property" value="#{5}"></property>

 浮点型:

<property name="property" value="#{89.3}"></property>

 科学计数:

<property name="property" value="#{1e4}"></property>

 字符串型:

<property name="name" value="#{'name'}"></property>
<property name="name" value='#{"name"}'></property>

 单引号和双引号都支持

布尔型:

<property name="name" value="#{false}"></property>

引用bean、properties和方法

通过bean的id引用bean:

<property name="property" value="#{otherBean}"></property>

 引用其他bean的属性:

<property name="property" value="#{otherBean.property}"></property>

 引用其他bean的调用方法:

<property name="name" value="#{otherBean.method()}"></property>

 可以调用工具方法进行结果处理:

<property name="name" value="#{otherBean.method().toUpperCase()}"></property>

 如果方法返回空值,则会抛出异常,如果要避免异常出现可以使用如下写法:

<property name="name" value="#{otherBean.method()?.toUpperCase()}"></property>

 操作类

调用静态方法和属性以及常量可以使用:

<property name="name" value="#{T(java.lang.Math).PI}"></property>

 在SpEL上执行的操作:

运算符类型 运算符
算数运算 +,-,*,/,%,^
关系运算 <,>,==,>=,<=,It,gt,,le,ge,eq
逻辑运算 and, or , not, |
条件运算 ?:
正则表达式 matchs

数值运算:

<property name="name" value="#{juggler.total + 40}"></property>
<property name="name" value="#{juggler.total / 40}"></property>
<property name="name" value="#{juggler.total * 40}"></property>
<property name="name" value="#{juggler.total % 40}"></property>

 比较运算:

<property name="name" value="#{juggler.total == 40}"></property>
<property name="name" value="#{juggler.total > 40}"></property>
<property name="name" value="#{juggler.total lt 40}"></property>

逻辑运算:

<property name="name" value="#{juggler.total > 40 and juggler.total < 80}"></property>
<property name="name" value="#{juggler.total > 40 or juggler.total < 80}"></property>
<property name="name" value="#{not juggler.total > 40}"></property>

 三元运算:

<property name="name" value="#{juggler.total == 40 ? '1' : '2'}"></property>

 三元运算变体:

<property name="name" value="#{juggler.total ?:  '2'}"></property>

 以上表达为如果juggler.total不为空则为本身的值,如果为空就为2

正则表达式:

<property name="name" value="#{juggler.name matchs '[a-zA-z0-9._%+-]+'}"></property>

在SpEL中筛选集合:

<property name="name" value="#{cities[2]}"></property>
 

 cities为在spring中定义的集合,该例为方位该集合中的第三个元素

调用集合中的方法:

<property name="name" value="#{cities[2].size()}"></property>

 访问map集合:

<property name="name" value="#{cities['key']}"></property>

 读取properties文件中的值:

<util:properties id="settings" location="classpath:settings.properties"></util:properties>  
	<bean id="flute" class="org.robbie.test.spring.beans.Flute">
		<property name="name" value="#{settins['name']}"></property>
	</bean>

 访问spring内置特殊属性的值:

访问环境变量:

<property name="name" value="#{systemEnvironment['JAVA_HOME']}"></property>

 访问启动参数:

<property name="name" value="#{systemProperties['application.home']}"></property>

查询集合成员:

使用.?[]

<property name="bigCities" value="#{cities.?[population gt 10000]}"></property>

 查询集合cities中人口数大于10000的城市元素,并将这些元素注入进属性当中

查询第一个匹配项:

<property name="bigCities" value="#{cities.^[population gt 10000]}"></property>

 查询集合cities中第一个匹配人口大于10000的元素,并进行属性注入

查询最后一个匹配项:

<property name="bigCities" value="#{cities.$[population gt 10000]}"></property>

  查询集合cities中最后一个匹配人口大于10000的元素,并进行属性注入

投影集合(根据某种条件筛选出一个新的集合)

<property name="bigCities" value="#{cities.![name]}"></property>

 把集合cities中每个元素的name属性进行重新组织,形成一个新的集合,然后将这个新的集合注入进属性当中

先查询集合再投影集合:

<property name="bigCities" value="#{cities.?[population gt 10000].![name]}"></property>

 在cities中查询人口大于10000的元素,并把这个元素的name属性的值重新组织成一个新的集合,将这个新的集合注入进属性当中

        SpEL非常的灵活,但是最终只是一组字符串的表达式,没有任何的校验,容易出现错误,按照书籍理解,如果传统的装配方式不能够满足时,再考虑SpEL方式进行装配。

猜你喜欢

转载自dynamicman.iteye.com/blog/2061758