zoukankan      html  css  js  c++  java
  • (转)Spring管理的Bean的生命周期

    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的生命周期进行下载。

  • 相关阅读:
    冒泡排序算法分析和实现
    选择排序算法分析与实现
    nio和 bio
    TCP三次握手
    IE input X 去掉文本框的叉叉和密码输入框的眼睛图标
    <%#eval() %>和<%#bind() %> 的区别
    <%#Eval() %>的常用方法
    C#(ASP.net)从其他网站抓取内容并截取有用信息
    JQuery写的一个简单的分页插件-2
    简单实用的jQuery分页插件
  • 原文地址:https://www.cnblogs.com/telwanggs/p/6913084.html
Copyright © 2011-2022 走看看