单实例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;
@Configuration
public 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 {
@Test
public 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 {
@Test
public 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;
@Configuration
public class MainConfigOfLifeCycle {
//我们在MainConfigOfLifeCycle配置类中的car()方法上通过@Scope注解将Car对象设置成多实例bean
@Scope("prototype")
@Bean(initMethod="init", destroyMethod="destroy")
public Car car() {
return new Car();
}
}
然后,我们修改一下IOCTest_LifeCycle类中的test01()方法,将关闭容器的那行代码给注释掉,如下所示。
@Test
public 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对象的代码,如下所示。
@Test
public 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的销毁方法
@Test
public 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...