单实例Bean的初始化与销毁

:::info XML配置方式 ::: 如果是使用XML配置文件的方式配置Bean的话,那么可以在标签中指定Bean的初始化和销毁方法,如下所示。

  1. <bean id="car" class="com.meimeixia.bean.Car" init-method="init" destroy-method="destroy">
  2. <property ...>...</property>
  3. <property ...>...</property>
  4. </bean>
  5. //这里,需要注意的是,在我们自己写的car类中,需要存在init()方法和destroy()方法。
  6. //而且Spring中还规定,这里的init()方法和destroy()方法必须是无参方法,但可以抛出异常。首先,创建一个名称为Car的类,这个类的实现比较简单,如下所示。
  7. package com.meimeixia.bean;
  8. public class Car {
  9. public Car() {
  10. System.out.println("car constructor...");
  11. }
  12. public void init() {
  13. System.out.println("car ... init...");
  14. }
  15. public void destroy() {
  16. System.out.println("car ... destroy...");
  17. }
  18. }

如果是使用@Bean注解配置Bean的话,那么可以这样指定初始化和销毁方法@Bean(initMethod="init", destroyMethod="destroy")

  1. package com.meimeixia.config;
  2. import org.springframework.context.annotation.Bean;
  3. import org.springframework.context.annotation.Configuration;
  4. import com.meimeixia.bean.Car;
  5. @Configuration
  6. public class MainConfigOfLifeCycle {
  7. @Bean(initMethod="init", destroyMethod="destroy")
  8. public Car car() {
  9. return new Car();
  10. }
  11. }

接着,我们就新建一个IOCTest_LifeCycle类来测试容器中的Car对象,该测试类的代码如下所示。

  1. package com.meimeixia.test;
  2. import org.junit.Test;
  3. import org.springframework.context.annotation.AnnotationConfigApplicationContext;
  4. import com.meimeixia.config.MainConfigOfLifeCycle;
  5. public class IOCTest_LifeCycle {
  6. @Test
  7. public void test01() {
  8. // 1. 创建IOC容器
  9. AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfigOfLifeCycle.class);
  10. System.out.println("容器创建完成");
  11. }
  12. }

对于单实例Bean对象来说,在Spring容器创建完成后就会对单实例Bean进行实例化。同时init要在constructor之后调用,因为初始化init要在实例化constructor之后

  1. car constructor...
  2. car ... init...
  3. 容器创建完成

运行上面的测试方法并没有打印出bean的销毁方法中的信息啊,那什么时候执行bean的销毁方法?
我们继续在IOCTest_LifeCycle类中的test01()方法中,添加关闭容器的代码,如下所示。

  1. package com.meimeixia.test;
  2. import org.junit.Test;
  3. import org.springframework.context.annotation.AnnotationConfigApplicationContext;
  4. import com.meimeixia.config.MainConfigOfLifeCycle;
  5. public class IOCTest_LifeCycle {
  6. @Test
  7. public void test01() {
  8. // 1. 创建IOC容器
  9. AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfigOfLifeCycle.class);
  10. System.out.println("容器创建完成");
  11. // 关闭容器
  12. applicationContext.close();
  13. }
  14. }

此时,我们再来运行IOCTest_LifeCycle类中的test01()方法,会发现输出的结果信息如下所示。

  1. car constructor...
  2. car ... init...
  3. 容器创建完成
  4. car ... destroy...

多实例Bean的初始化与销毁

前面,我们已经说了单实例Bean的初始化和销毁方法。接下来,我们来说下多实例Bean的初始化和销毁方法。我们将Car对象变成多实例Bean来验证下。

  1. package com.meimeixia.config;
  2. import org.springframework.context.annotation.Bean;
  3. import org.springframework.context.annotation.Configuration;
  4. import org.springframework.context.annotation.Scope;
  5. import com.meimeixia.bean.Car;
  6. @Configuration
  7. public class MainConfigOfLifeCycle {
  8. //我们在MainConfigOfLifeCycle配置类中的car()方法上通过@Scope注解将Car对象设置成多实例bean
  9. @Scope("prototype")
  10. @Bean(initMethod="init", destroyMethod="destroy")
  11. public Car car() {
  12. return new Car();
  13. }
  14. }

然后,我们修改一下IOCTest_LifeCycle类中的test01()方法,将关闭容器的那行代码给注释掉,如下所示。

  1. @Test
  2. public void test01() {
  3. // 1. 创建IOC容器
  4. AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfigOfLifeCycle.class);
  5. System.out.println("容器创建完成");
  6. // 关闭容器
  7. // applicationContext.close();
  8. }

接着,运行以上test01()方法,发现输出的结果信息如下所示。

  1. 容器创建完成

可以看到,当我们将Car对象设置成多实例Bean,并且没有通过getBean方法获取Bean实例对象时,Spring容器并没有执行Bean的构造方法、初始化方法和销毁方法。
说到这,我们就在IOCTest_LifeCycle类中的test01()方法里面添加一行获取Car对象的代码,如下所示。

  1. @Test
  2. public void test01() {
  3. // 1. 创建IOC容器
  4. AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfigOfLifeCycle.class);
  5. System.out.println("容器创建完成");
  6. applicationContext.getBean("car"); // 多实例bean在使用getBean获取的时候才创建对象
  7. // 关闭容器
  8. // applicationContext.close();
  9. }

再次运行以上test01()方法,输出的结果信息如下所示。

  1. 容器创建完成
  2. car constructor...
  3. car ... init...

可以看到,此时,结果信息中输出了构造方法和初始化方法中的信息。接下来来验证多实例Bean的销毁方法

  1. @Test
  2. public void test01() {
  3. // 1. 创建IOC容器
  4. AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfigOfLifeCycle.class);
  5. System.out.println("容器创建完成");
  6. applicationContext.getBean("car"); // 多实例bean在获取的时候才创建对象
  7. // 关闭容器
  8. applicationContext.close();
  9. }

此时,运行以上test01()方法,输出的结果信息如下所示。可以看到,多实例的bean在容器关闭的时候是不进行销毁的,scope = "prototype"意味着Spring将Bean返回给调用者, 由调用者管理 Bean 的生命周期,也就是说你每次获取时,IOC容器帮你创建出对象交还给你,至于要什么时候销毁这是你自己的事,Spring容器压根就不会再管理这些多实例的bean了。

  1. 容器创建完成
  2. car constructor...
  3. car ... init...