http://blog.csdn.net/yerenyuan_pku/article/details/52834011

bean的初始化时机

前面讲解了Spring容器管理的bean的作用域。接着我们就要思考一个问题:bean到底是在什么时候才进行实例化的呢?我们以这个问题为引子来展开本文的说明。 
bean对象无外乎是在以下两个时刻进行实例化的:

  1. 调用getBean()方法时。
  2. Spring容器启动时。

那么bean对象到底是在哪个时刻进行实例化的,这与Bean的作用域有着某种联系。我们以配置Spring管理的bean的作用域的案例为基础进行深入探讨。为了能够清楚地看到bean对象的实例化,我们需要修改PersonServiceBean类的代码为:

public class PersonServiceBean implements PersonService {
public PersonServiceBean() {
System.out.println("我被实例化了");
} @Override
public void save() {
System.out.println("我是save()方法");
}
}
  • 1
  • 当Spring的配置文件——beans.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.xsd"> <bean id="personService" class="cn.itcast.service.impl.PersonServiceBean"></bean> </beans>
    • 1

    即bean的作用域为singleton时,我们修改SpringTest类的代码为:

    public class SpringTest {
    
        @Test
    public void test() {
    ApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml"); // 实例化Spring容器
    } }
    • 1

    此时,测试test()方法,Eclipse控制台输出:

    我被实例化了

    这说明了当bean的作用域为singleton时,bean对象是在Spring容器启动时就进行创建了。即默认情况下会在容器启动时初始化bean,但我们也可以指定bean节点的lazy-init=“true”来延迟初始化bean,这时候,只有第一次获取bean会才初始化bean。如: 
    我们将Spring的配置文件——beans.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.xsd"> <bean id="personService" class="cn.itcast.service.impl.PersonServiceBean" lazy-init="true"></bean> </beans>
    • 1

    此时,测试test()方法,Eclipse控制台根本就不会输出这句话:

    我被实例化了

    lazy-init=”true”指定了不要在Spring容器启动时对这个bean进行实例化。 
    这时,只有将SpringTest类的代码修改为:

    public class SpringTest {
    
        @Test
    public void test() {
    ApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml"); // 实例化Spring容器
    PersonService personService = (PersonService) ctx.getBean("personService"); // 从Spring容器取得bean
    } }
    • 1

    再次测试test()方法,Eclipse控制台才会输出这句话:

    我被实例化了

    如果想对所有bean都应用延迟初始化,可以在根节点beans设置default-lazy-init=“true”,如下:

    <?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.xsd" default-lazy-init="true"> ...... </beans>
    • 1
  • 当Spring的配置文件——beans.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.xsd"> <bean id="personService" class="cn.itcast.service.impl.PersonServiceBean" scope="prototype"></bean> </beans>
    • 1

    即bean的作用域为prototype时,若SpringTest类的代码为:

    public class SpringTest {
    
        @Test
    public void test() {
    ApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml"); // 实例化Spring容器
    } }
    • 1

    测试test()方法,可以发现Eclipse控制台没输出这句话:

    我被实例化了

    这就说明了当bean的作用域为prototype时,bean对象并不会在Spring容器启动时就进行创建。 
    但是若将SpringTest类的代码改为:

    public class SpringTest {
    
        @Test
    public void test() {
    ApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml"); // 实例化Spring容器
    PersonService personService = (PersonService) ctx.getBean("personService"); // 从Spring容器取得bean
    } }
    • 1

    此时,再测试test()方法,可以发现Eclipse控制台输出了这句话:

    我被实例化了

    证实了当bean的作用域为prototype时,bean对象将会在调用getBean()方法时进行创建。

指定bean的初始化方法和销毁方法

我们希望在bean被初始化的时候,就初始化某些资源。为了达到这样的目的,我们可修改PersonServiceBean类的代码为:

public class PersonServiceBean implements PersonService {
public void init() {
System.out.println("初始化某些资源");
} public PersonServiceBean() {
System.out.println("我被实例化了");
} @Override
public void save() {
System.out.println("我是save()方法");
}
}
  • 1

这样,我们的目的就具体地成为:当Spring容器初始化PersonServiceBean对象之后,就要执行该对象的init()方法。为了达成这样的目的,只须修改Spring的配置文件——beans.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.xsd"> <bean id="personService" class="cn.itcast.service.impl.PersonServiceBean" lazy-init="false"
init-method="init" /> </beans>
  • 1
  • 2

若SpringTest类的代码为:

public class SpringTest {

    @Test
public void test() {
ApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml"); // 实例化Spring容器
} }
  • 1

测试test()方法,Eclipse控制台将打印: 

现在我们又希望在bean被销毁的时候,就释放或关闭某些资源。为了达到这样的目的,我们可修改PersonServiceBean类的代码为:

public class PersonServiceBean implements PersonService {
public void init() {
System.out.println("初始化某些资源");
} public PersonServiceBean() {
System.out.println("我被实例化了");
} @Override
public void save() {
System.out.println("我是save()方法");
} /**
* bean到底是什么时候销毁的呢?如果没有人为地删除它,默认该bean一直在Spring容器中,
* 也就是说随着Spring容器的关闭,该bean才会被销毁。
*/
public void destroy() {
System.out.println("释放初始化的资源");
}
}
  • 1

试着思考这样一个问题:bean对象到底是什么时候销毁的呢?答案是:如果没有人为地删除它,默认该bean一直在Spring容器中,也就是说随着Spring容器的关闭,该bean才会被销毁。 
紧接着,我们要修改Spring的配置文件——beans.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.xsd"> <bean id="personService" class="cn.itcast.service.impl.PersonServiceBean" lazy-init="false"
init-method="init" destroy-method="destroy" /> </beans>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

最后,我们要修改测试类——SpringTest.java的代码为:

public class SpringTest {

    @Test
public void test() {
// ApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml"); // 实例化Spring容器 AbstractApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml");
ctx.close(); // 正常关闭Spring容器
} }
  • 1

此时,测试test()方法,Eclipse控制台将打印: 

这就是Spring管理的Bean的生命周期。源码可点击Spring管理的Bean的生命周期进行下载。

(转)Spring管理的Bean的生命周期的更多相关文章

  1. Spring 容器中 Bean 的生命周期

    Spring 容器中 Bean 的生命周期 1. init-method 和 destory-method 方法 Spring 初始化 bean 或销毁 bean 时,有时需要作一些处理工作,因此 s ...

  2. Spring 学习笔记---Bean的生命周期

    生命周期图解 由于Bean的生命周期经历的阶段比较多,我们将通过一个图形化的方式进行描述.下图描述了BeanFactory中Bean生命周期的完整过程: Bean 的生命周期从Spring容器着手实例 ...

  3. Spring容器中bean的生命周期以及关注spring bean对象的后置处理器:BeanPostProcessor(一个接口)

    Spring IOC 容器对 Bean 的生命周期进行管理的过程: 1.通过构造器或工厂方法创建 Bean 实例 2.为 Bean 的属性设置值和对其他 Bean 的引用 3.将 Bean 实例传递给 ...

  4. Spring实战(二)Spring容器和bean的生命周期

    引入问题: 在XML配置文件中配置bean后,这些文件又是如何被加载的?它们被加载到哪里去了? Spring容器——框架核心 1.什么是Spring容器?它的功能是什么? 在基于Spring的应用中, ...

  5. Spring基础14——Bean的生命周期

    1.IOC容器中的Bean的生命周期方法 SpringIOC容器可以管理Bean的生命周期,Spring允许在Bean生命周期的特定点执行定制的任务.SpringIOC容器对Bean的生命周期进行管理 ...

  6. spring(二):bean的生命周期

    bean的生命周期指的是bean的创建——>初始化——>销毁的过程,该过程是由spring容器进行管理的 我们可以自定义bean初始化和销毁的方法:容器在bean进行到当前生命周期时,调用 ...

  7. spring框架中Bean的生命周期

    一.Bean 的完整生命周期 在传统的Java应用中,bean的生命周期很简单,使用Java关键字 new 进行Bean 的实例化,然后该Bean 就能够使用了.一旦bean不再被使用,则由Java自 ...

  8. (spring-第1回【IoC基础篇】)Spring容器中Bean的生命周期

    日出日落,春去秋来,花随流水,北雁南飞,世间万物皆有生死轮回.从调用XML中的Bean配置信息,到应用到具体实例中,再到销毁,Bean也有属于它的生命周期. 人类大脑对图像的认知能力永远高于文字,因此 ...

  9. spring中的bean的生命周期

    bean的生命周期:bean的创建 —— 初始化 ——销毁的过程 容器管理bean的生命周期,我们可以自定义初始化和销毁方法,容器在bean进行到当前生命周期就会调用我们的方法 在xml配置文件中是在 ...

随机推荐

  1. 机器学习 Hidden Markov Models 2

    Hidden Markov Models 下面我们给出Hidden Markov Models(HMM)的定义,一个HMM包含以下几个要素: ∏=(πi)表示初始状态的向量.A={aij}状态转换矩阵 ...

  2. Ruby nokogiri 解析xml的简单实例

    require 'nokogiri'XML_FILE = "C:\\Users\\chenpassion\\Desktop\\20130806.xml"xml = Nokogiri ...

  3. Vue中devtools安装使用

    vue.js的devtools安装 安装 1.github下载地址:https://github.com/vuejs/vue-devtools 2.下载好后进入vue-devtools-master工 ...

  4. Rational Rose 2007 &Rational Rose 2003 下载及破解方法和汉化文件下载

    Rational Rose 2007 &Rational Rose 2003 下载及破解方法和汉化文件下载 分类: 其它2010-08-10 13:28 12926人阅读 评论(4) 收藏 举 ...

  5. 什么是位、字节、字、KB、MB?

    1. 位(bit)是计算机里最小的数据单位,每一位的状态只能是0或者1 2. 字节(Byte)      1Byte = 8 bit      它是存储空间的基本计量单位,1byte可以存储一个英文字 ...

  6. iOS 拼音 Swift K3Pinyin

    iOS 系统方法支持直接获取拼音,避免了之前各种第三方引入各种MAP或者资源文件.下面是一个Swift版本的简单示例: // swift 4.0 func pinyin(_ string: Strin ...

  7. hdoj3711【水】

    题意: 给你两个集合,对于每个B集合的元素,从A集合找一个数使得a^b的二进制的1个数最少. 思路: 直接搞= = #include <bits/stdc++.h> using names ...

  8. bzoj 4550: 小奇的博弈【博弈论+dp】

    首先看出终止状态是全都堆在左边或者右边,然后发现黑的向左白的向右是最优策略(如果不能这样了也就该输了) 然后就不会了 参考 http://www.cnblogs.com/CQzhangyu/p/770 ...

  9. bzoj 1176 [Balkan2007]Mokia 【CDQ分治】

    W过大,很难在线维护,考虑离线算法 给每个操作加一个时间属性n,显然,对于n=i的询问,对它有影响的修改只在n<i中,所以可以CDQ(因为是按时间序读进来的,所以不用排序了 对于统计矩形和,可以 ...

  10. python中用代码实现99乘法表

    第一种:使用for遍历循环嵌套 ,): ,x+): print("%s*%s=%s" % (y,x,x*y),end=" ") print("&quo ...