Spring简单的实例(一)中,我们说过Bean的生命周期,知道默认情况下Bean是处于单例状态,这里还需要再提一下:
首先抛出一个问题:在Spring中我们通过getBean(name)获得的实例,那么我们每次获取的实例化对象是否唯一?
我们可以通过代码来验证结论:
在配置文件Beans.xml中配置(基本不变):
<bean id="userBean" class="com.xuli.spring.implement.UserBean"></bean>
接着直接可以写测试方法,我们可以通过“==”进行测试:
@Test /* * 测试Bean在初始化时,是否重新实例了一个新的实例 */ public void UserTest3() { ApplicationContext context = new ClassPathXmlApplicationContext("Beans.xml"); UserBean user = (UserBean) context.getBean("userBean"); UserBean user1 = (UserBean) context.getBean("userBean"); System.out.println(user == user1); }
运行结果如下所示:
如此可以验证之前的结论:
默认Bean是单例,任何人获取该Bean实例的都为同一个实例。
在配置文件节点Bean下有一个属性scope,在默认情况下它是这样的:scope= “singleton”,是单例! :
<bean id="userBean" class="com.xuli.spring.implement.UserBean" scope="singleton"></bean>
将scope属性指定为prototype:
<bean id="userBean" class="com.xuli.spring.implement.UserBean" scope="prototype"></bean>
这时候我们在运行测试:是不是发现控制台打印出false 了。
这时就不是唯一的实例对象了!
bean元素scope属性配置Bean的作用域这里在强调一下:
<bean>元素scope属性,在spring规范中scope属性有五个取值:
1. scope="singleton" 单例,在Spring IoC容器中仅存在一个Bean实例(默认的scope)
默认情况下:托管给spring默认在spring容器中只有一个Bean实例对象.
2. scope="prototype" 多例,每次从容器中调用Bean时,都返回一个新的实例,即每次调用getBean()时,相当于执行new XxxBean()
3. scope="request" 用于web开发,该作用域仅适用于WebApplicationContext环境.
每次HTTP请求都会创建一个新的Bean,将Bean放入request范围,request.setAttribute("xxx"),在同一个request 获得同一个Bean
4. scope="session" 用于web开发, 该作用域仅适用于WebApplicationContext环境.
同一个HTTP Session 共享一个Bean,不同Session使用不同Bean,将Bean 放入Session范围
5. scope="globalSession"该作用域仅适用于WebApplicationContext环境.
一般用于Porlet应用环境 , 分布式系统存在全局session概念,如果不是porlet环境,globalSession 等同于Session . Porlet是Servlet的一个升级,Porlet主要用于分布式系统.
在默认的情况下IOC容器在启动时会初始化Bean,但是我们可以通过Lazy-init=“true”来延迟初始化Bean,这时只有第一次获取Bean时才会初始化Bean。配置代码如下:
<bean id="userBean" class="com.xuli.spring.implement.UserBean" Lazy-init="true"></bean>
如果想要对所有Bean都是用延迟初始化那么可以在Beans后加这样的属性:
<beans default-lazy-init="true"...</beans>
这样就OK了。
如果我们想在UserBean实例化时,调用初始化方法可以使用这样的节点属性init-method,销毁方法也可以通过destory-method调用。
具体实现代码如下:
首先在Beans.xml下配置:
<bean id="userBean" class="com.xuli.spring.implement.UserBean" scope="singleton" init-method="init" destroy-method="destroy">
在UserBean中加入初始化和销毁方法,init,destroy 方法。
代码如下:
/* * 实现PersonBean的接口 */ public class UserBean implements UserBeanimpl { @Override public void show() { // TODO Auto-generated method stub System.out.println("hello xuli "); } //初始化方法 public void init(){ System.out.println("Bean被初始化了"); } //销毁方法 public void destroy(){ System.out.println("Bean被销毁了"); } }
测试方法:
@Test // 使用类构造器直接实例化测试 public void UserTest() { // ApplicationContext context = new // ClassPathXmlApplicationContext("Beans.xml"); // 读取配置Bean文件 ApplicationContext context = new FileSystemXmlApplicationContext("classpath:Beans.xml"); // 获得在Bean.xml里注入的Bean对象 UserBean user = (UserBean) context.getBean("userBean"); // 调用其对象内的方法 user.show(); }
是不是发现销毁方法无效?
这里可以在测试方法内调用user.destroy()方法直接销毁。
也可以通过关闭spring容器调用destory方法,这样不需要user.destory()。demo:
@Test // 使用类构造器直接实例化测试 public void UserTest() { // ApplicationContext context = new // ClassPathXmlApplicationContext("Beans.xml"); // 读取配置Bean文件 ApplicationContext context = new FileSystemXmlApplicationContext("classpath:Beans.xml"); // 获得在Bean.xml里注入的Bean对象 UserBean user = (UserBean) context.getBean("userBean"); // 调用其对象内的方法 user.show(); ((AbstractApplicationContext) context).close(); }
这样就可以销毁啦。
测试结果: