ITEEDU

Spring Gossip: 自动绑定

接续 属性参考 的内容。

直接指定值或是使用<ref>直接指定参考至其它的Bean,Spring也支持隐式的自动绑定,您可以透过类型(byType)或名称(byName)将Bean绑定至其它Bean上对应的属性,下面是个byType的例子:
beans-config.xml
<?xml version="1.0" encoding="UTF-8"?> 
<!DOCTYPE beans PUBLIC "-//SPRING/DTD BEAN/EN"
"http://www.springframework.org/dtd/spring-beans.dtd">

<beans>
<bean id="dateBean" class="java.util.Date"/>
<bean id="helloBean"
class="onlyfun.caterpillar.HelloBean"
autowire="byType"
>
<property name="helloWord">
<value>Hello!</value>
</property>
</bean>
</beans>
在定义档中,并没有指定helloBean的Date属性,而是透过自动绑定,由于autowire指定了byType,所以会根据helloBean的 Date属性所接受的型态,判断是否有类似的型态对象,并将之绑定至helloBean的Date属性上,如果byType无法完成绑定,则丢出 org.springrframework.beans.factory.UnsatisfiedDependencyExcpetion例外。

您也可以指定byName来绑定,则Spring会根据bean的别名与属性名称是否符合来进行自动绑定,举个例子来说,如果是byName而Date属性要完成依赖注入的话,则必须修改一下第一个Bean的id值为date:
beans-config.xml
<?xml version="1.0" encoding="UTF-8"?> 
<!DOCTYPE beans PUBLIC "-//SPRING/DTD BEAN/EN"
"http://www.springframework.org/dtd/spring-beans.dtd">

<beans>
<bean id="date" class="java.util.Date"/>
<bean id="helloBean"
class="onlyfun.caterpillar.HelloBean"
autowire="byName">
<property name="helloWord">
<value>Hello!</value>
</property>
</bean>
</beans>
如果byName无法完成绑定,则属性维持未绑定状态。

在建构方法上,也可以尝试进行自动绑定,例如若HelloBean.java修改如下:
HelloBean.java
package onlyfun.caterpillar; 

import java.util.Date;

public class HelloBean {
private String helloWord;
private Date date;

public HelloBean() {
}

public HelloBean(Date date) {
this.date = date;
}

public void setHelloWord(String helloWord) {
this.helloWord = helloWord;
}
public String getHelloWord() {
return helloWord;
}
public void setDate(Date date) {
this.date = date;
}
public Date getDate() {
return date;
}
}
您可以如下定义beans-config.xml:
beans-config.xml
<?xml version="1.0" encoding="UTF-8"?> 
<!DOCTYPE beans PUBLIC "-//SPRING/DTD BEAN/EN"
"http://www.springframework.org/dtd/spring-beans.dtd">

<beans>
<bean id="date" class="java.util.Date"/>
<bean id="helloBean"
class="onlyfun.caterpillar.HelloBean"
autowire="constructor">
<property name="helloWord">
<value>Hello!</value>
</property>
</bean>
</beans>
由于autowire设定为constructor,在建立绑定关系时,Spring容器会试图比对容器中的Bean及相关的建构方法,在型态上是否有符 合,如果有的话,则选用该建构方法来建立Bean实例,例如上例中,HelloBean的带参数建构方法与date这个Bean的型态相符,于是选用该建 构方法来建构实例,并将date这个Bean注入给它,如果无法完成绑定,则丢出 org.springframework.beans.factory.UnsatisfiedDependencyException例外。

还想再偷懒的话。就使用autodetect,例如:
beans-config.xml
<?xml version="1.0" encoding="UTF-8"?> 
<!DOCTYPE beans PUBLIC "-//SPRING/DTD BEAN/EN"
"http://www.springframework.org/dtd/spring-beans.dtd">

<beans>
<bean id="date" class="java.util.Date"/>
<bean id="helloBean"
class="onlyfun.caterpillar.HelloBean"
autowire="autodetect">
<property name="helloWord">
<value>Hello!</value>
</property>
</bean>
</beans>
使用autodetect时,会尝试使用constructor,然后使用byType,哪一个先符合就先用。

隐式的自动绑定没办法从定义档中,清楚的看到是否每个属性都完成设定,我们可以加入相依检查,在<bean>上加入dependency- check,有四种相依检查方式:simple、objects、all、none。第一个只检查简单的属性,像是原生(primitive)数据型态或 字符串对象,objects检查对象属性,all则检查全部的属性,none是预设,表示不检查相依性,例如:
beans-config.xml
<?xml version="1.0" encoding="UTF-8"?> 
<!DOCTYPE beans PUBLIC "-//SPRING/DTD BEAN/EN"
"http://www.springframework.org/dtd/spring-beans.dtd">

<beans>
<bean id="date" class="java.util.Date"/>
<bean id="helloBean"
class="onlyfun.caterpillar.HelloBean"
autowire="autodetect"
dependency-check="all">
<property name="helloWord">
<value>Hello!</value>
</property>
</bean>
</beans>
如果相依检查发现有未完成的依赖关系,则运行时会丢出org.springframework.beans.factory.UnsatisfiedDependencyException。