Spring -bean对象的生命周期

原文链接

一,单例管理的对象:(scope="singleton")

1.默认情况下,spring在读取xml文件的时候,就会创建对象。
2.在创建的对象的时候(先调用构造器),会去调用init-method=".."属性值中所指定的方法.

3.对象在被销毁的时候,会调用destroy-method="..."属性值中所指定的方法.(例如调用container.destroy()方法的时候)

4.lazy-init="true",可以让这个对象在第一次被访问的时候创建

二,非单例管理的对象:(scope="prototype")

1.spring读取xml文件的时候,不会创建对象.
2.在每一次访问这个对象的时候,spring容器都会创建这个对象,并且调用init-method=".."属性值中所指定的方法.
3.对象销毁的时候,spring容器不会帮我们调用任何方法,因为是非单例,这个类型的对象有很多个,spring容器一旦把这个对象交给你之后,就不再管理这个对象了.

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()方法");
    }
}
  • 当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>

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

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

    此时,测试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>

    此时,测试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
        }
    
    }

    再次测试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>
  • 当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>

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

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

    测试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
        }
    
    }

    此时,再测试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()方法");
    }
}

这样,我们的目的就具体地成为:当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>

若SpringTest类的代码为:

public class SpringTest {

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

}

测试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("释放初始化的资源");
    }
}

试着思考这样一个问题: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>

最后,我们要修改测试类——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容器
    }

}

此时,测试test()方法,Eclipse控制台将打印: 
这里写图片描述 
这就是Spring管理的Bean的生命周期


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值