Bean的生命周期从容器new了一个Bean之后开始,在关闭容器时结束,如果直接关闭虚拟机且没有写关闭容器的代码那么将不会看到生命周期结束时执行的方法
方法1——在创建Bean中添加init()、destroy()函数
在创建Bean中添加init()、destroy()函数并在ApplicationContext.xml中建立对应关系
public class BookDaoImpl implements BookDao {
public void save(){
System.out.println("Dao save");
}
//表示Bean初始化对应操作
public void init(){
System.out.println("init...");
}
//表示Bean销毁前对应操作
public void destroy(){
System.out.println("destroy...");
}
}
在ApplicationContext.xml中添加对应关系
<!--2.配置bean
bean标签表示配置bean
id属性给bean起名字
class属性表示给bean定义类型
init-method对应Bean的初始化方法
destroy-method对应Bean的销毁方法-->
<bean id="bookDao" class="com.itheima.dao.impl.BookDaoImpl" init-method="init" destroy-method="destroy"/>
运行测试
public class App {
public static void main(String[] args){
ApplicationContext ctx=new ClassPathXmlApplicationContext("ApplicationContext.xml");
BookDao bookDao= (BookDao) ctx.getBean("bookDao");
bookDao.save();
}
}
运行结果
可以看到,并未执行destroy()方法
这是因为仅有关闭容器时,Bean的生命周期才结束,有两种方式关闭容器
1.通过直接关闭虚拟机的方式关闭容器
调用ctx.close()方法可以直接关闭虚拟机
public class App {
public static void main(String[] args){
// ctx.close()方法在ClassPathXmlApplicationContext中
ClassPathXmlApplicationContext ctx=new ClassPathXmlApplicationContext("ApplicationContext.xml");
BookDao bookDao= (BookDao) ctx.getBean("bookDao");
bookDao.save();
//关闭虚拟机
ctx.close();
}
}
运行结果
2.设置容器关闭勾子
public class App {
public static void main(String[] args){
//ctx.registerShutdownHook()方法在ClassPathXmlApplicationContext中
ClassPathXmlApplicationContext ctx=new ClassPathXmlApplicationContext("ApplicationContext.xml");
BookDao bookDao= (BookDao) ctx.getBean("bookDao");
bookDao.save();
//在关闭虚拟机之前先关闭容器
ctx.registerShutdownHook();
}
}
运行结果
方法2——使用Spring提供的InitializingBean, DisposableBean接口
无需配置ApplicationContext.xml,可直接在service中写入
public class BookServiceImpl implements BookService, InitializingBean, DisposableBean {
private BookDao bookDao;
//提供对应的set方法 该方法是容器调用的
public void setBookDao(BookDao bookDao) {
System.out.println("set..");
this.bookDao = bookDao;
}
//Bean生命周期结束调用
@Override
public void destroy() throws Exception {
System.out.println("service destroy...");
}
//Bean创建调用
//此处afterPropertiesSet是指在容器调用setBookDao方法之后调用
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("service init...");
}
}
我们不修改xml中的配置,保持对Bean的生命周期的添加则BookDao和bookService中添加的方法都会调用,且有先后顺序
<!--配置bean
bean标签表示配置bean
id属性给bean起名字
class属性表示给bean定义类型-->
<bean id="bookDao" class="com.itheima.dao.impl.BookDaoImpl" init-method="init" destroy-method="destroy"/>
<bean id="bookService" name="service service2 service3" class="com.itheima.service.impl.BookServiceImpl">
<!--配置service与Dao的关系
property标签表示配置当前bean的属性
name属性表示配置哪一个具体的属性
ref属性表示参照哪一个bean-->
<property name="bookDao" ref="bookDao"/>
</bean>
测试
public class App {
public static void main(String[] args){
ClassPathXmlApplicationContext ctx=new ClassPathXmlApplicationContext("ApplicationContext.xml");
BookDao bookDao= (BookDao) ctx.getBean("bookDao");
bookDao.save();
//在关闭虚拟机之前先关闭容器
ctx.registerShutdownHook();
}
}
运行结果
此处可以看到容器运行使用Bean时的过程——
1.虚拟机开启,容器启动,在容器中创建Bean,此时调用Bean中的init()方法
2.通过调用对应service中setBean()方法将Bean与service关联
3.调用service中的初始化方法afterPropertiesSet()
4.执行service中的操作
5.执行完成,即将关闭容器,调用service中的析构方法destroy()
6.调用Bean中的销毁方法
7.容器关闭,虚拟机关闭