bean的生命周期
1、bean的实例化:bean在何时被实例化?
2、bean的初始化:init-method:指定初始化回调方法,在实例化 bean 时,立即调用该方法
3、bean的销毁:destroy-method:销毁回调方法,只有从容器中移除 bean 之后,才能调用该方法。
4、默认的初始化和销毁方法
beans标签内部 default-init-method=“init” default-destroy-method=“destroy”
bean在何时被实例化?
大家已经学过servlet的生命周期了,servlet是被web容器进行管理的,而servlet的实例化有两种方式:web容器在加载时和servlet被访问时。与servlet类似,bean是被spring容器所管理的,所以bean的实例化无外乎两种情况:
1、Spring容器启动时。
2、调用getBean()方法时。
这里我们要注意的是,bean的实例化时间跟Bean的作用域也有一定的关系,我们以上节内容spring bean的作用域为基础举例
1)当bean的作用域为singleton时
修改Demo类,添加构造方法:
public class Demo {
public Demo(){
System.out.println("正在实例化...");
}
private String name;
}
然后修改spring.xml的配置文件如下,使用scope的默认值:
<?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="demo" class="com.oak.junit.day01.Demo"></bean>
</beans>
即bean的作用域为singleton时,我们修改测试类的代码,添加测试方法为:
@Test
public void testLife(){
//实例化Spring容器
ApplicationContext ctx = new ClassPathXmlApplicationContext("spring.xml");
}
控制台输出:正在实例化...
说明了当bean的作用域为singleton时,bean对象是在Spring容器启动时就进行创建了。即默认情况下会在容器启动时初始化bean。
我们也可以指定bean的初始化时机为在调用getBean()方法时被初始化,使用bean元素的lazy-init属性:
lazy-init:true,延迟初始化的 bean 告诉 Ioc 容器在它第一次被请求时,而不是在启动时去创建一个 bean 实例。
修改bean节点代码为:
<!-- 构造器实例化 -->
<bean id="demo" class="com.oak.junit.day01.Demo" scope="prototype"
lazy-init="true"></bean>
直接测试发现并没有任何输出,更改测试方法为:
@Test
public void testLife(){
//实例化Spring容器
ApplicationContext ctx = new ClassPathXmlApplicationContext("spring.xml");
Demo demo=ctx.getBean("demo",Demo.class);
}
重新测试发现控制台输出:正在实例化...
则说明了lazy-init=”true”指定了不要在Spring容器启动时对这个bean进行实例化。
如果想对所有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>
2)当bean的作用域为prototype时
修改spring.xml配置文件,删除bean节点的lazy-init=”true”,代码如下:
<!-- 构造器实例化 -->
<bean id="demo" class="com.oak.junit.day01.Demo" scope="prototype"></bean>
增加测试方法如下:
@Test
public void testLifePrototype(){
//实例化Spring容器
ApplicationContext ctx = new ClassPathXmlApplicationContext("spring.xml");
}
进行测试发现没有任何输出,修改测试方法,增加getBean()方法的调用
@Test
public void testLifePrototype(){
//实例化Spring容器
ApplicationContext ctx = new ClassPathXmlApplicationContext("spring.xml");
Demo demo=ctx.getBean("demo",Demo.class);
}
控制台输出:正在实例化...
说明当bean的作用域为prototype时,bean对象并不会在Spring容器启动时就进行创建。 bean对象将会在调用getBean()方法时进行创建。
bean的初始化
我们希望在bean被初始化的时候,就初始化某些资源。为了达到这样的目的,我们可以给类添加初始化方法:
public class Demo {
//定义初始化方法
public void init(){
System.out.println("正在被初始化...");
}
public Demo(){
System.out.println("正在实例化...");
}
private String name;
}
在Spring.xml中为bean指定初始化方法,使用bean元素的init-method属性:
<!-- 构造器实例化 -->
<bean id="demo" class="com.oak.junit.day01.Demo" lazy-init="false" init-method="init"></bean>
执行测试方法:
@Test
public void testInit(){
//实例化Spring容器
ApplicationContext ctx = new ClassPathXmlApplicationContext("spring.xml");
}
控制台输出:
正在实例化...
正在初始化...
bean的销毁
现在我们又希望在bean被销毁的时候,就释放或关闭某些资源。为了达到这样的目的,我们可以给类添加指定的销毁方法:
public class Demo {
//初始化方法
public void init(){
System.out.println("正在初始化...");
}
public Demo(){
System.out.println("正在实例化...");
}
//销毁方法
public void destroy() {
System.out.println("释放初始化的资源");
}
private String name;
}
在Spring.xml中为bean指定初始化方法,使用bean元素的init-method属性:
<!-- 构造器实例化 -->
<bean id="demo" class="com.oak.junit.day01.Demo" lazy-init="false" init-method="init" destroy-method="destroy"></bean>
添加测试方法并执行:
@Test
public void testDestory(){
//实例化Spring容器
AbstractApplicationContext ctx = new ClassPathXmlApplicationContext("spring.xml");
//正常关闭Spring容器
ctx.close();
}
控制台输出:
正在实例化...
正在初始化...
释放初始化的资源
PS:bean销毁的时机
bean到底是什么时候销毁的呢?如果没有人为地删除它,默认该bean一直在Spring容器中, 也就是说随着Spring容器的关闭,该bean才会被销毁。
默认的初始化和销毁方法
在beans标签内部添加 default-init-method=“init” default-destroy-method=“destroy”
修改spring.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"
default-init-method="init"
default-destroy-method="destroy">
<!-- 构造器实例化 -->
<bean id="demo" class="com.oak.junit.day01.Demo" lazy-init="false"></bean>
</beans>
添加测试方法:
@Test
public void testLife(){
//实例化Spring容器
AbstractApplicationContext ctx = new ClassPathXmlApplicationContext("spring.xml");
ctx.close();
}
控制台输出:
正在实例化...
正在初始化...
释放初始化的资源