依赖注入--如果A依赖于B,则B实例不再由A负责生成,而有容器负责生成,并注入给A实例,因此称为依赖注入,也称为控制反转。
配置依赖
根据注入方式的不同,bean的依赖注入通常表现为如下两种形式:
1,属性:通过property属性来指定对应的设值注入。
2,构造器参数:通过constructor-arg属性来指定对应的构造注入。
在Spring在实例化BeanFactory时,通常会校验BeanFactory中的每一个Bean的配置。这些校验包括:
1.bean引用的合作者指向一个合法的bean.
2.对于被设置为pre-instantiated的bean的singleton行为,Spring会在创建BeanFactory时,同时实例化bean.实例化bean时,也会将它所依赖的bean一起实例化。
此外,BeanFactory与ApplicationContext实例化容器中的bean的时机不同:前者在程序需要bean实例时才创建Bean;而后者在加载ApplicationContext实例时,会自动实例化容器中的全部bean.
ApplicationContext是默认预实例化singleton bean。ApplicationContext实例化过程比BeanFactory时间和内存占用率大,但可以在ApplicationContext创建时就检验出配置错误。当然可以通过lazy-load属性为“true”来改变ApplicationContext的默认行为!
bean的依赖通常可以接受如下元素指定值:
1.value.
2.ref.
3.bean.
4.list.set.map.以及props.
首先来看看value元素。
value元素用于确定字符串参数。XML文档解析器解析以String解析出这些数据,然后将这些参数由PropertyEditors完成转换(从java.lang.String类型转换为所需的参数类型)。
for example:
-------------------------------------------------------------------------------------------
package org.viking.spring.itf;
public interface ValueElementItf
{
public void shows();
}
-------------------------------------------------------------------------------------------
package org.viking.spring.imp;
import org.viking.spring.itf.ValueElementItf;
public class ValueElement implements ValueElementItf {
private int integerProperty;
private double doubleProperty;
private String email;
public void shows()
{
System.out.println(integerProperty);
System.out.println(doubleProperty);
System.out.println(email);
}
public void setIntegerProperty(int integerProperty) {
this.integerProperty = integerProperty;
}
public void setDoubleProperty(double doubleProperty) {
this.doubleProperty = doubleProperty;
}
public void setEmail(String email) {
this.email = email;
}
}
-------------------------------------------------------------------------------------------
<?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-2.0.xsd">
<bean id="value" class="org.viking.spring.imp.ValueElement">
<property name="integerProperty">
<value>1</value>
</property>
<property name="doubleProperty">
<value>2.3</value>
</property>
</bean>
</beans>
-------------------------------------------------------------------------------------------
package org.viking.spring.test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.viking.spring.itf.Person;
import org.viking.spring.itf.ValueElementItf;
import junit.framework.TestCase;
public class TestElement extends TestCase
{
public void testValueElement()
{
ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");
ValueElementItf value = (ValueElementItf)app.getBean("value");
value.shows();
}
}
-------------------------------------------------------------------------------------------
value元素的值可以通过<null/>元素指定为空。
把上面的applicationContext.xml文件代码改一下。
-------------------------------------------------------------------------------------------
<?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-2.0.xsd">
<bean id="value" class="org.viking.spring.imp.ValueElement">
<property name="integerProperty">
<value>1</value>
</property>
<property name="doubleProperty">
<value>2.3</value>
</property>
<property name="email">
<value></value>
</property>
</bean>
</beans>
-------------------------------------------------------------------------------------------
改过之后的测试打印出了Null.
接着是ref元素
如果需要为bean注入的属性是容器中的某个bean实例,推荐使用ref。
ref元素通常有两个属性:
1.bean
2.local
bean用于指定在不同一个xml配置文件中的bean,而local用于指定同一个xml配置文件中的其他bean,并且local属性值只能是其他bean的id属性,让Spring在解析XML时,验证bean的名称。
bean元素
如果某个bean的依赖bean不想被Spring容器直接访问,则可以使用嵌套bean。
嵌套bean只对嵌套它的外部bean有效,而Spring容器无法直接访问嵌套bean,因此嵌套bean无需id属性。
嵌套bean的配置形式,保证嵌套bean不能被容器访问,提高了程序的内聚性。
嵌套bean的例子会在下一个元素讲解中使用到!
list,set,map,以及props元素
list,set,map和props元素分别用来设置类型为List,Set,Map和Properties的属性值,用来为bean注入集合值。
for example:
-------------------------------------------------------------------------------------------
package org.viking.spring.itf;
public interface Person
{
public void shows();
}
-------------------------------------------------------------------------------------------
package org.viking.spring.imp;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import org.viking.spring.itf.Person;
public class Chinese implements Person
{
private List schools = new ArrayList();
private Map score = new HashMap();
private Properties health = new Properties();
private Set axes = new HashSet();
public void shows()
{
System.out.println(schools);
System.out.println(score);
System.out.println(health);
System.out.println(axes);
}
public void setSchools(List schools) {
this.schools = schools;
}
public void setScore(Map score) {
this.score = score;
}
public void setHealth(Properties health) {
this.health = health;
}
public void setAxes(Set axes) {
this.axes = axes;
}
}
-------------------------------------------------------------------------------------------
package org.viking.spring.imp;
public class ValueElement
{
public ValueElement()
{
System.out.println("嵌套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-2.0.xsd">
<bean id="chinese" class="org.viking.spring.imp.Chinese">
<property name="schools">
<list>
<value>小学</value>
<value>中学</value>
<value>大学</value>
</list>
</property>
<property name="score">
<map>
<entry key="数学">
<value>87</value>
</entry>
<entry key="英语">
<value>89</value>
</entry>
<entry key="语文">
<value>82</value>
</entry>
</map>
</property>
<property name="health">
<props>
<prop key="血压">正常</prop>
<prop key="身高">175</prop>
</props>
</property>
<property name="axes">
<set>
<value>字符串斧子</value>
<ref local="value"/>
<bean class="org.viking.spring.imp.ValueElement"></bean>
<!--这就是嵌套bean-->
</set>
</property>
</bean>
</beans>
-------------------------------------------------------------------------------------------
package org.viking.spring.test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.viking.spring.itf.Person;
import org.viking.spring.itf.ValueElementItf;
import junit.framework.TestCase;
public class TestElement extends TestCase
{
public void testCollection()
{
ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");
Person p1 = (Person)app.getBean("chinese");
p1.shows();
}
}
-------------------------------------------------------------------------------------------
map元素entry的值以及set元素的值都可以使用如下元素:
1.vlaue:确定基本数据类型值或字符串类型值。
2.ref:确定另外一个bean为属性值。
3.bean:确定一个嵌套bean为属性值。
4.list,set,map,以及props:确定集合值为属性值。
这么说可能有点抽象,大家运行一下以上代码,就一清二楚了!
在实际应用中,某个实例的属性可能是某个方法的返回值,类的field值,或者属性值。这种非常规的方法Spring同样支持!Spring甚至支持将bean实例的属性值,方法返回值及field值直接赋给一个变量。
好了,今天就到这,明天接着写注入属性值!
-------以上的文字以及代码摘录于李刚写的《轻量级J2EE开发企业应用实战》,代码有少许变动!
Identify the aspects of your application that vary and separate them from what stays the same.