目录
(4)BookDaoImpl实现类中新增两个方法(模拟初始、消亡)。
(5)设置关闭钩子(registerShutdownHook()方法)。
(6)close()方法与registerShutdownHook()方法区别。
四、实现指定接口(InitializingBean、DisposableBean)完成生命周期控制。
(1)实现destory()、afterPropertiesSet()方法。
一、bean生命周期的基本介绍。
本篇博客的学习——围绕bean生命周期的控制。
(1)bean生命周期。
- 简单来说。就是一个东西从创建到消亡的整个过程。(如:人从出生到死亡的过程)
- bean其实就是对象。也就是这个对象从创建到销毁的整个过程。
(2)bean生命周期的控制。
- 对bean生命周期的控制——在bean创建后到销毁之前可以做的事情。
二、依赖坐标、涉及的接口与实现类。
(1)spring-context。
<dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>5.3.18</version> </dependency> </dependencies>
(2)service层。
BookService接口。
package com.fs.service; public interface BookService { /** * service层save方法 */ void save(); }
BookServiceImpl实现类。
package com.fs.service.impl; import com.fs.dao.BookDao; import com.fs.service.BookService; public class BookServiceImpl implements BookService { /*private BookDao bookDao = new BookDaoImpl();*/ private BookDao bookDao; //提供成员属性的setter方法 public void setBookDao(BookDao bookDao) { this.bookDao = bookDao; } @Override public void save() { System.out.println("book service save..."); bookDao.save(); } }
(3)dao层。
- BookDao接口。
package com.fs.dao; public interface BookDao { /** * dao层的save方法 */ void save(); }
- BookDaoImpl实现类。
package com.fs.dao.impl; import com.fs.dao.BookDao; public class BookDaoImpl implements BookDao { @Override public void save() { System.out.println("book dao save..."); } }
(4)BookDaoImpl实现类中新增两个方法(模拟初始、消亡)。
- init()方法。bean加载前的数据准备(初始)。
- destroy()方法。bean消亡之前做的事情。
package com.fs.dao.impl; import com.fs.dao.BookDao; public class BookDaoImpl implements BookDao { @Override public void save() { System.out.println("book dao save..."); } //模拟bean初始化方法(如加载资源、读取文件) public void init(){ System.out.println("dao init..."); } //模拟bean消亡前方法 public void destory(){ System.out.println("dao destory..."); } }
(5)测试类。
- 通过IoC容器获取对应id的bean。
- 通过bean对象调用自己的save()方法。
package com.fs.test; import com.fs.dao.impl.BookDaoImpl; import com.fs.service.BookService; import org.springframework.context.support.ClassPathXmlApplicationContext; public class App { public static void main(String[] args) { //获取IoC容器,加载配置文件 ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("springContext.xml"); //通过id获取指定bean Object obj = context.getBean("bookDao"); BookDaoImpl bookDao = (BookDaoImpl) obj; bookDao.save(); } }
三、spring配置文件控制bean生命周期。
- 因为是在BookDaoImpl中新增的两个模拟初始和销毁方法,所以是对应配置文件中class为BookDaoImpl的bean进行处理。
(1)init-method属性。
- 将对应的自己创建的初始化方法赋值给该属性即可。
(2)destory-method属性。
- 将对应的自己创建的销毁方法赋值给该属性即可。
(3)运行测试类,查看结果。
- 发现destroy()方法并未按预期的运行。
- 因为在主方法(main)中的获取的bean对象执行完自己的save()方法后,程序执行完毕,虚拟机就退出了(程序是运行在java虚拟机中)。而相应的destroy()方法来不及执行。
(4)close()方法。
- 解决方法一。在程序退出前,执行关闭容器操作。(close()方法)
- 追溯到源头——类ClassPathXmlApplicationContext其父父...接口就有这个方法。
(5)设置关闭钩子(registerShutdownHook()方法)。
- 简单理解。容器启动以后做一个标记。在虚拟机退出之前,别忘记让容器关闭后再退出。
- 使用方法:调用容器对象的registerShutdownHook()方法即可。此方法可以在前面写,也可以在最后写。
(6)close()方法与registerShutdownHook()方法区别。
- close()方法关闭容器的方式相对比较暴力。
- 如果把close()方法放在获取bean前面,加载配置文件后。初始化和销毁都会照常完成,但是从容器获取bean就会报错!因为容器都关闭了,就不能再从其中获取到对应bean。
- 因为以后做的项目或应用都是基于web来开发的。而关闭容器的操作应该伴随着tomcat一起进行的。所以都是了解学习一下。
四、实现指定接口(InitializingBean、DisposableBean)完成生命周期控制。
(1)实现destory()、afterPropertiesSet()方法。
- 这里为了测试方便,换成在BookServiceImpl实现类中完成操作。
- 按照规定,就肯定要实现两个对应接口。再实现接口中的两个方法。
package com.fs.service.impl; import com.fs.dao.BookDao; import com.fs.service.BookService; import org.springframework.beans.factory.DisposableBean; import org.springframework.beans.factory.InitializingBean; public class BookServiceImpl implements BookService, InitializingBean, DisposableBean { /*private BookDao bookDao = new BookDaoImpl();*/ private BookDao bookDao; //提供成员属性的setter方法 public void setBookDao(BookDao bookDao) { this.bookDao = bookDao; } @Override public void save() { System.out.println("book service save..."); bookDao.save(); } @Override public void destroy() throws Exception { //测试打印 System.out.println("service destory..."); } @Override public void afterPropertiesSet() throws Exception { //测试打印 System.out.println("service init..."); } }
- 执行测试类。
- 如在配置文件中给init-method、destory-method属性配置的效果一样。
(2)afterPropertiesSet()方法。
- 功能:在Bean的所有依赖(通过Setter或构造函数注入)设置完成后,执行自定义初始化操作。(如资源检查、数据连接建立等)
- 通常触发时机:Spring容器完成属性注入后自动调用,确保初始化代码能安全访问已注入的属性。
- 测试。在BookServiceImpl的setter方法(dao依赖注入service)中打印一句话。发现afterPropertiesSet方法的调用在setter方法之后,也就是执行时机在完成依赖注入后。
- 当属性设置之后,才会执行这个初始化方法(afterPropertiesSet()方法)。
- 它们之间是有严格的执行顺序的!
五、bean生命周期的几个阶段(小结)。
- 需要了解的是:bean在整个初始化到销毁的过程中经历的几个阶段。
(1)初始化容器。
- <1>创建bean(对象)。分配内存。可以简单理解为new!
- <2>执行构造方法。
- <3>执行属性注入。(如setter操作)
- <4>执行bean的初始化方法。
(2)使用bean。(获取指定bean)
- 执行bean的相关业务操作。
(3)关闭(销毁)容器。
- 执行bean的销毁方法。
(4)bean销毁的时机。
- 容器关闭前触发bean的销毁!!!
(5)关闭容器的2种方式。
1、手动"暴力"关闭容器。
- 容器对象调用ConfigurableApplicationcontext接口的close()操作。
2、注册关闭钩子。(指定虚拟机先关闭容器再退出虚拟机)
- 容器对象调用ConfigurableApplicationcontext接口的registerShutdownHook()操作。