环境准备
- Eclipse上新建一个简单的maven工程,Artifact Id选择maven-archetype-quickstart;
- 添加spring-context依赖;
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>3.2.16.RELEASE</version> </dependency>
- resources目录下添加spring的配置文件spring.xml;
- 开始编写bean及测试代码;
Bean的创建方式
默认构造方法创建bean
首先,写一个杂技师类;
在spring配置文件中声明该杂技师Bean(未配置<constructor-arg>,将使用默认构造方法);
<bean id="duke" class="cn.edu.hdu.sia.chapter2.Juggler"> </bean>
在main方法中使用该杂技师bean;
public static void main(String[] args) { ApplicationContext ctx = new ClassPathXmlApplicationContext("spring.xml"); Performer performer = (Performer) ctx.getBean("duke"); performer.perform(); }
非默认构造方法创建bean
构造方法参数为基本数据类型的情况
接着上例的例子,可以在配置bean的时候,往构造方法传入参数,如下配置,将调用public Juggler(int beanBags)构造方法创建杂技师bean;
<bean id="duke" class="cn.edu.hdu.sia.chapter2.Juggler"> <constructor-arg value="15" /> </bean>
构造方法参数为对象引用类型的情况
现在,我们将要给杂技师增加吟诗行为;
先定义一个诗歌背诵接口:
package cn.edu.hdu.sia.chapter2; public interface Poem { public void recite(); }
再写一个吟诗实现类:
package cn.edu.hdu.sia.chapter2; public class JingYeSi implements Poem{ public void recite() { System.out.println("床前明月光~"); } }
然后编写吟诗杂耍类:
在spring配置文件中声明该杂技师Bean,注意构造方法的第二个参数为对象引用,引用id为“jingyesi”的bean;
可以用index属性指定构造方法参数索引下标,type指定构造方法参数类型,name指定构造方法参数名,用于区分不同的参数;
<bean id="jingyesi" class="cn.edu.hdu.sia.chapter2.JingYeSi"> </bean> <bean id="poeticDuke" class="cn.edu.hdu.sia.chapter2.PoeticJuggler"> <constructor-arg value="15" /> <constructor-arg ref="jingyesi" /> </bean>
最后参考前面写的main方法测试perform的执行情况,发现该杂技师Bean不仅能杂耍,还能吟诗;
工厂方法创建bean
当构造方法为私有的时候,是不能够通过构造方法创建bean的,这时候一般通过工厂方法创建,如下为一个典型的单例类,其构造方法为私有属性:
package cn.edu.hdu.sia.chapter2; public class Stage { private Stage() { } private static class StageSingletonHolder { static Stage stage = new Stage(); } public static Stage getInstance() { return StageSingletonHolder.stage; } public void printDescription(){ System.out.println("this is a stage."); } }
要创建该bean,需要在spring配置文件中做如下配置:
可以用factory-bean属性设置指定的工厂bean,用<constructor-arg>标签往factory-method传入参数;
<bean id="theStage" class="cn.edu.hdu.sia.chapter2.Stage" factory-method="getInstance" />
bean的作用域
所有的bean在spring上下文范围内默认都是“单例”的,即只有一个实例,注意,这里的单例指的是spring上下文范围内的单例;要修改该配置项,只需要配置scope属性,scope默认是singleton,可配置的属性值如下列表:
作用域 |
定义 |
singleton |
在每一个Spring容器中,一个Bean定义只有一个对象实例(默认) |
prototype |
运行Bean的定义可以被实例化任意次(每次调用都创建一个实例) |
request |
在一次HTTP请求中,每个Bean定义对应一个实例,该作用域仅在基于Web的Spring上下文(例如Spring MVC)中才有效 |
session |
在一个HTTP Session中,每个Bean定义对应一个实例,该作用域仅在基于Web的Spring上下文(例如Spring MVC)中才有效 |
global-session |
在一个全局HTTP Session中,每个Bean定义对应一个实例,该作用域仅在Portlet上下文中才有效 |
bean的初始化和销毁
bean的初始化指bean对象创建后执行的一些操作,如初始化等;
bean的销毁指bean从spring上下文移除时执行的一些操作,如清理,释放资源等;
可以对bean配置init-method和destroy-method属性,指定其初始化方法和销毁方法,如下配置:
<bean id="theStage" class="cn.edu.hdu.sia.chapter2.Stage" factory-method="getInstance" init-method="init" destroy-method="destroy"/>
其中init和destroy为该bean中自定义的方法,可在里面添加一些初始化和销毁操作;
另外,我们还可以通过实现InitializingBean和DisposableBean接口来完成bean的初始化和销毁操作,具体需要实现以下两个方法即可:
/** * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet() * @throws Exception */ public void afterPropertiesSet() throws Exception { // TODO Auto-generated method stub } /** * @see org.springframework.beans.factory.DisposableBean#destroy() * @throws Exception */ public void destroy() throws Exception { // TODO Auto-generated method stub }
实现这些接口的缺点是bean与spring api产生了耦合,因此还是推荐使用配置init-method和destroy-method属性实现初始化和销毁;
额外说下,在非web应用程序中,关闭spring上下文可以通过调用close方法或registerShutdownHook方法,区别如下:
close:立刻关闭spring上下文(容器);
registerShutdownHook:等到JVM关闭的时候再关闭spring上下文(容器);
如下代码段示例,bean的销毁方法不会马上执行,而是在JVM销毁后才执行:
public static void main(String[] args) { AbstractApplicationContext ctx = new ClassPathXmlApplicationContext("spring.xml"); Stage stage = (Stage) ctx.getBean("theStage"); stage.printDescription(); ctx.registerShutdownHook(); try { TimeUnit.MILLISECONDS.sleep(1000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println("start JVM desdroy."); }
配置bean的属性
bean属性为基本数据类型情况(bean中需要有setter方法)
<bean id="peter" class="cn.edu.hdu.sia.chapter2.User"> <property name="name" value="Peter"></property> <property name="age" value="22"></property> </bean>
bean属性为对象引用的情况
属性bean通过外部注入
<bean id="jingyesi" class="cn.edu.hdu.sia.chapter2.JingYeSi"></bean> <bean id="peter" class="cn.edu.hdu.sia.chapter2.User"> <property name="name" value="Peter"></property> <property name="age" value="22"></property> <property name="poem" ref="jingyesi"></property> </bean>
属性bean通过内部注入,同样适用于构造方法的入参<constructor-arg>,注意:外部其它bean不能引用内部bean
<bean id="peter" class="cn.edu.hdu.sia.chapter2.User"> <property name="name" value="Peter"></property> <property name="age" value="22"></property> <property name="poem"> <bean class="cn.edu.hdu.sia.chapter2.JingYeSi"/> </property> </bean>
另外,还可以使用spring的p命名空间来配置属性:
<bean id="peter" class="cn.edu.hdu.sia.chapter2.User" p:name="Peter" p:age="22" />
bean属性为集合的情况
可使用如下四种配置
集合元素 |
用途 |
对应实际数据类型 |
<list> |
装配list类型的值,允许重复 |
数组或java.util.Collection |
<set> |
装配set类型的值,不允许重复 |
|
<map> |
装配map类型的值,名称和值可以是任意类型 |
java.util.Map |
<props> |
装配properties类型的值,名称和值必须都是String型 |
java.util.Properties |
List、Set、Array
这里的list也可以用set替换,区别仅仅是允不允许重复
<bean id="jingyesi" class="cn.edu.hdu.sia.chapter2.JingYeSi"></bean> <bean id="xinglunan" class="cn.edu.hdu.sia.chapter2.XingLuNan"></bean> <bean id="peter" class="cn.edu.hdu.sia.chapter2.User"> <property name="name" value="Peter"></property> <property name="age" value="22"></property> <property name="poemList"> <list> <ref bean="jingyesi" /> <ref bean="xinglunan" /> </list> </property> </bean>
map
<bean id="jingyesi" class="cn.edu.hdu.sia.chapter2.JingYeSi"></bean> <bean id="xinglunan" class="cn.edu.hdu.sia.chapter2.XingLuNan"></bean> <bean id="peter" class="cn.edu.hdu.sia.chapter2.User"> <property name="name" value="Peter"></property> <property name="age" value="22"></property> <property name="poemMap"> <map> <entry key="jingyesi" value-ref="jingyesi"/> <entry key="xinglunan" value-ref="xinglunan"/> </map> </property> </bean>
Properties
<bean id="peter" class="cn.edu.hdu.sia.chapter2.User"> <property name="name" value="Peter"></property> <property name="age" value="22"></property> <property name="properties"> <props> <prop key="test1">111</prop> <prop key="test2">222</prop> </props> </property> </bean>
bean属性值设为null情况
<bean id="peter" class="cn.edu.hdu.sia.chapter2.User"> <property name="name" value="Peter"></property> <property name="age" value="22"></property> <property name="properties"> <null/> </property> </bean>