单实例Bean的初始化与销毁
:::info XML配置方式 ::: 如果是使用XML配置文件的方式配置Bean的话,那么可以在标签中指定Bean的初始化和销毁方法,如下所示。
<bean id="car" class="com.meimeixia.bean.Car" init-method="init" destroy-method="destroy"><property ...>...</property><property ...>...</property></bean>//这里,需要注意的是,在我们自己写的car类中,需要存在init()方法和destroy()方法。//而且Spring中还规定,这里的init()方法和destroy()方法必须是无参方法,但可以抛出异常。首先,创建一个名称为Car的类,这个类的实现比较简单,如下所示。package com.meimeixia.bean;public class Car {public Car() {System.out.println("car constructor...");}public void init() {System.out.println("car ... init...");}public void destroy() {System.out.println("car ... destroy...");}}
如果是使用@Bean注解配置Bean的话,那么可以这样指定初始化和销毁方法@Bean(initMethod="init", destroyMethod="destroy")
package com.meimeixia.config;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import com.meimeixia.bean.Car;@Configurationpublic class MainConfigOfLifeCycle {@Bean(initMethod="init", destroyMethod="destroy")public Car car() {return new Car();}}
接着,我们就新建一个IOCTest_LifeCycle类来测试容器中的Car对象,该测试类的代码如下所示。
package com.meimeixia.test;import org.junit.Test;import org.springframework.context.annotation.AnnotationConfigApplicationContext;import com.meimeixia.config.MainConfigOfLifeCycle;public class IOCTest_LifeCycle {@Testpublic void test01() {// 1. 创建IOC容器AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfigOfLifeCycle.class);System.out.println("容器创建完成");}}
对于单实例Bean对象来说,在Spring容器创建完成后就会对单实例Bean进行实例化。同时init要在constructor之后调用,因为初始化init要在实例化constructor之后
car constructor...car ... init...容器创建完成
运行上面的测试方法并没有打印出bean的销毁方法中的信息啊,那什么时候执行bean的销毁方法?
我们继续在IOCTest_LifeCycle类中的test01()方法中,添加关闭容器的代码,如下所示。
package com.meimeixia.test;import org.junit.Test;import org.springframework.context.annotation.AnnotationConfigApplicationContext;import com.meimeixia.config.MainConfigOfLifeCycle;public class IOCTest_LifeCycle {@Testpublic void test01() {// 1. 创建IOC容器AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfigOfLifeCycle.class);System.out.println("容器创建完成");// 关闭容器applicationContext.close();}}
此时,我们再来运行IOCTest_LifeCycle类中的test01()方法,会发现输出的结果信息如下所示。
car constructor...car ... init...容器创建完成car ... destroy...
多实例Bean的初始化与销毁
前面,我们已经说了单实例Bean的初始化和销毁方法。接下来,我们来说下多实例Bean的初始化和销毁方法。我们将Car对象变成多实例Bean来验证下。
package com.meimeixia.config;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.context.annotation.Scope;import com.meimeixia.bean.Car;@Configurationpublic class MainConfigOfLifeCycle {//我们在MainConfigOfLifeCycle配置类中的car()方法上通过@Scope注解将Car对象设置成多实例bean@Scope("prototype")@Bean(initMethod="init", destroyMethod="destroy")public Car car() {return new Car();}}
然后,我们修改一下IOCTest_LifeCycle类中的test01()方法,将关闭容器的那行代码给注释掉,如下所示。
@Testpublic void test01() {// 1. 创建IOC容器AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfigOfLifeCycle.class);System.out.println("容器创建完成");// 关闭容器// applicationContext.close();}
接着,运行以上test01()方法,发现输出的结果信息如下所示。
容器创建完成
可以看到,当我们将Car对象设置成多实例Bean,并且没有通过getBean方法获取Bean实例对象时,Spring容器并没有执行Bean的构造方法、初始化方法和销毁方法。
说到这,我们就在IOCTest_LifeCycle类中的test01()方法里面添加一行获取Car对象的代码,如下所示。
@Testpublic void test01() {// 1. 创建IOC容器AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfigOfLifeCycle.class);System.out.println("容器创建完成");applicationContext.getBean("car"); // 多实例bean在使用getBean获取的时候才创建对象// 关闭容器// applicationContext.close();}
再次运行以上test01()方法,输出的结果信息如下所示。
容器创建完成car constructor...car ... init...
可以看到,此时,结果信息中输出了构造方法和初始化方法中的信息。接下来来验证多实例Bean的销毁方法
@Testpublic void test01() {// 1. 创建IOC容器AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfigOfLifeCycle.class);System.out.println("容器创建完成");applicationContext.getBean("car"); // 多实例bean在获取的时候才创建对象// 关闭容器applicationContext.close();}
此时,运行以上test01()方法,输出的结果信息如下所示。可以看到,多实例的bean在容器关闭的时候是不进行销毁的,scope = "prototype"意味着Spring将Bean返回给调用者, 由调用者管理 Bean 的生命周期,也就是说你每次获取时,IOC容器帮你创建出对象交还给你,至于要什么时候销毁这是你自己的事,Spring容器压根就不会再管理这些多实例的bean了。
容器创建完成car constructor...car ... init...
