在Spring中,对象无需自己负责查找或创建与其关联的其他对象,相反,容器负责把需要相互协作的对象引用赋予各个对象。
创建应用对象之间协作关系的行为即为装配。这也是依赖注入的本质。
1.创建Spring配置
Spring是一个基于容器的框架。如果没有配置Spring,那么它就是一个空容器。
Spring容器提供了两种配置Bean的方式:传统方法,配置XML配置文件;Spring3.0提供了基于Java注解的配置方式。
注入依赖的方式:
>.构造器注入:
eg.1默认构造器注入
<bean id="duke" class = "com.springaction.springidol.Juggler">
</bean>
eg.2有参构造函数注入
<bean id="duke" class = "com.springaction.springidol.Juggler">
<!--设置构造器参数为15-->
<constructor-arg value="15">
</constructor-arg>
</bean>
对应的构造函数为
public void Juggler(int bags)
{
this.bags = bags;
}
eg.3构造函数参数有对象
<bean id="duke" class = "com.springaction.springidol.Juggler">
<!--构造器一个参数为15-->
<constructor-arg value="15">
</constructor-arg>
<!--构造器另一个参数通过ref将属性为sonnet29的Bean引用传递给构造器-->
<constructor-arg ref="sonnet29">
</constructor-arg>
</bean>
<bean id="sonnet29" class="com.springaction.springidol.Sonnet29">
</bean>
当Spring加载到sonnet29和duke的<bean>声明时,它所执行的逻辑本质上是如下的Java代码:
Poem sonnet29 = new Sonnet29();
Performer duke = new PoeticJuggler(15, sonnet29);
>.通过工厂方法创建Bean
如果要声明的Bean没有公有构造函数,则可以通过静态工厂方法实例化对象
<!--通过getInstance方法创建Stage单例对象-->
<bean id="stage" class="com.springactin.springidol.Stage"
factory-method="getInstance">
</bean>
2.Bean作用域
所有的Spring Bean默认都是单例的。
如果要Spring在每次请求时都生成一个新的Bean实例,可以给Bean配作用域: scope="prototype"
Spring提供了如下作用域选项:
注:Spring的单例Bean只能保证在每个应用上下文中只有一个Bean实例。
3.Bean的初始化和销毁
当实例化一个Bean时,可能需要执行一些初始化操作来确保Bean处于可用状态。同样,当不再需要Bean,将其从容器中移除时,可能还需要按顺序执行一些清除工作。为了满足初始化和销毁Bean的需求,Bean提供了Bean生命周期的钩子方法。
为了定义Bean的初始化和销毁操作,只需要使用init-method和detroy-method参数来配置</bean>元素。
eg.
<bean id="test_Bean" class="test.domain.TestClass"
init-method="start"
destroy-method="stop">
</bean>
当test_Bean Bean实例化后悔立即调用start()方法做初始化操作。当该Bean从容器中移除和销毁前,会调用stop()方法完成一些清理工作。
4.注入Bean的属性
Spring可借助属性的set方法来配置属性的值,以实现setter方法的注入。前提是JavaBean的属性拥有一组存取器方法,以setXXX()和getXXX()形式存在。
>.注入简单的值
<bean id="test_Bean" class="spirng.domain.test.TestClass">
<property name="age" value="25" />
<property name="sex" value="male" />
</bean>
Spring将根据Bean属性的类型自动判断value值的正确类型。
>.引用其他Bean:依赖注入的真正价值在于把相互协作的对象装配在一起,而不需要这些对象自己负责装配。
eg.
<bean id="kenny" class="spring.domain.Instrumentalist">
<property name="song" value="Jingle Bells" />
<property name="instrument" ref="piano" />
</bean>
<bean id="piano" class="spring.domain.Piano" />
这样,kenny就可以演奏钢琴了,这是面向接口编程的好处。Instrumentalist这个类只是通过Instrument接口来了解它的instrument属性。所以Instrumentalist不需要任何改变就可以支持一个Instrument接口的新实现。
>.内部bean
上面的piano Bean可以被任何其他Bean所共享。
<bean id="kenny" class="spring.domain.Instrumentalist">
<property name="song" value="Jingle Bells" />
<property name="instrument" >
<bean class="spring.domain.Piano" >
</bean>
</bean>
上面这个内部Bean就为kenney所独自拥有了,其他Bean无法获得。
内部Bean并不仅限于setter注入,还可以把内部Bean装配到构造方法的入参中。
>.使用Spring命名空间p装配属性。
>.装配集合:配置集合类型的Bean属性时,Spring提供了4种类型的集合配置元素。
eg1.装配List、Set和Array
public class OneManBand implements Performer
{
private Collection<Instrument> instruments;
public OneManBand()
{
}
public void perform()
throw PerformanceException
{
for(Instrument instrument: instruments)
{
instrument.play();
}
}
public void setInstruments(Collection<Instrument> instruments)
{
this.instruments = instruments;
}
}
对于上面的JavaBean,Spring提供乐器集合方法如下:
(1).List
<bean id="hank" class="spring.domain.test.OneManBand">
<property name="instruments">
<list>
<ref bean="guitar"/>
<ref bean="cymbal"/>
<ref bean="harmonica" />
</list>
</property>
</bean>
(2).Set:将上面的 <list> 换成 <set> 即可。
无论<list>还是<set>都可用来装配类型为Collection的任意实现或者数组的属性。
eg2.装配Map集合
public class OneManBand implements Performer
{
private Collection<String, Instrument> instruments;
public OneManBand()
{
}
public void perform()
throw PerformanceException
{
for(String key: instruments.keySet())
{
Instrument instrument = instruments.get(key);
instrument.play();
}
}
public void setInstruments(Map<String, Instrument> instruments)
{
//以Map类型注入instruments
this.instruments = instruments;
}
}
<bean id="hank" class="spring.domain.test.OneManBand">
<property name="instruments">
<map>
<entry key="GUITAR" bean="guitar"/>
<entry key="CYMBAL" bean="cymbal"/>
<entry key="HARMONICA" bean="harmonica" />
</map>
</property>
</bean>
>.使用SpEL表达式装配:可以为属性装配只有在运行期才知道的值。