一、什么是生命周期

  • 首先理解下什么是生命周期?

    • 从创建到消亡的完整过程,例如人从出生到死亡的整个过程就是一个生命周期。

  • bean生命周期是什么?

    • bean对象从创建到销毁的整体过程。

  • bean生命周期控制是什么?

    • 在bean创建后到销毁前做一些事情。

二、环境准备

环境搭建:

  • 创建一个Maven项目

  • pom.xml添加依赖

  • resources下添加spring的配置文件applicationContext.xml

最终项目的结构如下:

(1)项目中添加BookDao、BookDaoImpl、BookService和BookServiceImpl类

public interface BookDao {
   public void save();
}

public class BookDaoImpl implements BookDao {
   public void save() {
       System.out.println("book dao save ...");
  }
}

public interface BookService {
   public void save();
}

public class BookServiceImpl implements BookService{
   private BookDao bookDao;

   public void setBookDao(BookDao bookDao) {
       this.bookDao = bookDao;
  }

   public void save() {
       System.out.println("book service save ...");
       bookDao.save();
  }
}

(2)resources下提供spring的配置文件

<?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="bookDao" class="com.itheima.dao.impl.BookDaoImpl"/>
</beans>

(3)编写AppForLifeCycle运行类,加载Spring的IOC容器,并从中获取对应的bean对象

public class AppForLifeCycle {
   public static void main( String[] args ) {
       ApplicationContext ctx = new
      ClassPathXmlApplicationContext("applicationContext.xml");
       BookDao bookDao = (BookDao) ctx.getBean("bookDao");
       bookDao.save();
  }
}

三、生命周期设置

接下来,在上面这个环境中来为BookDao添加生命周期的控制方法,具体的控制有两个阶段:

  • bean创建之后,想要添加内容,比如用来初始化需要用到资源

  • bean销毁之前,想要添加内容,比如用来释放用到的资源

步骤1:添加初始化和销毁方法

针对这两个阶段,我们在BooDaoImpl类中分别添加两个方法,方法名任意

public class BookDaoImpl implements BookDao {
   public void save() {
       System.out.println("book dao save ...");
  }
   //表示bean初始化对应的操作
   public void init(){
       System.out.println("init...");
  }
   //表示bean销毁前对应的操作
   public void destory(){
       System.out.println("destory...");
  }
}
步骤2:配置生命周期

在配置文件添加配置,如下:

<bean id="bookDao" class="com.itheima.dao.impl.BookDaoImpl" init-method="init" destroy-method="destory"/>
步骤3:运行程序

运行AppForLifeCycle打印结果为:

从结果中可以看出,init方法执行了,但是destroy方法却未执行,这是为什么呢?

  • Spring的IOC容器是运行在JVM中

  • 运行main方法后,JVM启动,Spring加载配置文件生成IOC容器,从容器获取bean对象,然后调方法执行

  • main方法执行完后,JVM退出,这个时候IOC容器中的bean还没有来得及销毁就已经结束了

  • 所以没有调用对应的destroy方法

知道了出现问题的原因,具体该如何解决呢?

四、close关闭容器

  • ApplicationContext中没有close方法

  • 需要将ApplicationContext更换成ClassPathXmlApplicationContext

    ClassPathXmlApplicationContext ctx = new
       ClassPathXmlApplicationContext("applicationContext.xml");
  • 调用ctx的close()方法

    ctx.close();
  • 运行程序,就能执行destroy方法的内容

这种方式比较暴力,直接就关闭掉容器了,接下来介绍另一种方式,

五、注册钩子关闭容器

  • 在容器未关闭之前,提前设置好回调函数,让JVM在退出之前回调此函数来关闭容器

  • 调用ctx的registerShutdownHook()方法

  • 是全局变量,方法放置位置无所谓

    ctx.registerShutdownHook();

    注意:registerShutdownHook在ApplicationContext中也没有

  • 运行后,查询打印结果

两种方式介绍完后,close和registerShutdownHook选哪个?

相同点:这两种都能用来关闭容器

不同点:close()是在调用的时候关闭,registerShutdownHook()是在JVM退出前调用关闭。

分析上面的实现过程,会发现添加初始化和销毁方法,即需要编码也需要配置,实现起来步骤比较多也比较乱。

Spring提供了两个接口来完成生命周期的控制,好处是可以不用再进行配置init-methoddestroy-method

接下来在BookServiceImpl完成这两个接口的使用:

修改BookServiceImpl类,添加两个接口InitializingBeanDisposableBean并实现接口中的两个方法afterPropertiesSetdestroy

public class BookServiceImpl implements BookService, InitializingBean, DisposableBean {
   private BookDao bookDao;
   public void setBookDao(BookDao bookDao) {
       this.bookDao = bookDao;
  }
   public void save() {
       System.out.println("book service save ...");
       bookDao.save();
  }
   public void destroy() throws Exception {
       System.out.println("service destroy");
  }
   public void afterPropertiesSet() throws Exception {
       System.out.println("service init");
  }
}

重新运行AppForLifeCycle类

那第二种方式的实现,我们也介绍完了。

小细节

  • 对于InitializingBean接口中的afterPropertiesSet方法,翻译过来为属性设置之后

  • 对于BookServiceImpl来说,bookDao是它的一个属性

  • setBookDao方法是Spring的IOC容器为其注入属性的方法

  • 思考:afterPropertiesSet和setBookDao谁先执行?

    • 从方法名分析,猜想应该是setBookDao方法先执行

    • 验证思路,在setBookDao方法中添加一句话

      public void setBookDao(BookDao bookDao) {
             System.out.println("set .....");
             this.bookDao = bookDao;
        }
    • 重新运行AppForLifeCycle,打印结果如下:

      验证的结果和我们猜想的结果是一致的,所以初始化方法会在类中属性设置之后执行。

六、bean生命周期总结

(1)关于Spring中对bean生命周期控制提供了两种方式:

  • 在配置文件中的bean标签中添加init-methoddestroy-method属性

  • 类实现InitializingBeanDisposableBean接口。

(2)对于bean的生命周期控制在bean的整个生命周期中所处的位置如下:

  • 初始化容器

    • 1.创建对象(内存分配)

    • 2.执行构造方法

    • 3.执行属性注入(set操作)

    • 4.执行bean初始化方法

  • 使用bean

    • 1.执行业务操作

  • 关闭/销毁容器

    • 1.执行bean销毁方法

(3)关闭容器的两种方式:

  • ConfigurableApplicationContext是ApplicationContext的子类

    • close()方法

    • registerShutdownHook()方法

Java开发学习(五)----bean的生命周期的更多相关文章

  1. Spring 学习笔记---Bean的生命周期

    生命周期图解 由于Bean的生命周期经历的阶段比较多,我们将通过一个图形化的方式进行描述.下图描述了BeanFactory中Bean生命周期的完整过程: Bean 的生命周期从Spring容器着手实例 ...

  2. spring深入学习(二)-----bean的生命周期、IOC容器bean装配

    bean的生命周期 1.实例化Bean对于BeanFactory容器,当客户向容器请求一个尚未初始化的bean时,或初始化bean的时候需要注入另一个尚未初始化的依赖时,容器就会调用createBea ...

  3. Spring4学习笔记 - Bean的生命周期

    1 Spring IOC 容器对 Bean 的生命周期进行管理的过程: 1)通过构造器或工厂方法创建 Bean 实例 2)为 Bean 的属性设置值和对其他 Bean 的引用 3)调用 Bean 的初 ...

  4. Java多线程学习(三)---线程的生命周期

    线程生命周期 摘要: 当线程被创建并启动以后,它既不是一启动就进入了执行状态,也不是一直处于执行状态.在线程的生命周期中,它要经过新建(New).就绪(Runnable).运行(Running).阻塞 ...

  5. Java开发学习(三)----Bean基础配置及其作用范围

    一.bean基础配置 对于bean的基础配置如下 <bean id="" class=""/> 其中,bean标签的功能.使用方式以及id和clas ...

  6. Java开发学习(四)----bean的三种实例化方式

    一.环境准备 准备开发环境 创建一个Maven项目 pom.xml添加依赖 resources下添加spring的配置文件applicationContext.xml 最终项目的结构如下:    二. ...

  7. Spring Bean的生命周期,《Spring 实战》书中的官方说法

    连着两天的面试 ,都问到了 Spring 的Bean的生命周期,其中还包括 昨晚一波阿里的电话面试.这里找到了Spring 实战中的官方说法.希望各位要面试的小伙伴记住,以后有可能,或者是有时间 去看 ...

  8. 深究Spring中Bean的生命周期

    前言 这其实是一道面试题,是我在面试百度的时候被问到的,当时没有答出来(因为自己真的很菜),后来在网上寻找答案,看到也是一头雾水,直到看到了<Spring in action>这本书,书上 ...

  9. Spring02——Spring 中 Bean 的生命周期及其作用域

    在前一篇文章中,我们已经介绍了 Spring IOC 的相关知识,今天将为个位介绍 Spring 中 Bean 的相关知识.关注我的公众号「Java面典」,每天 10:24 和你一起了解更多 Java ...

随机推荐

  1. PostgreSQL执行计划:Bitmap scan VS index only scan

    之前了解过postgresql的Bitmap scan,只是粗略地了解到是通过标记数据页面来实现数据检索的,执行计划中的的Bitmap scan一些细节并不十分清楚.这里借助一个执行计划来分析bitm ...

  2. Installing github.com/mdempsky/gocode FAILED ----vscode安装go插件中的一些坑

    问题前景: 最近在使用vscode,编写一些go的代码,但发现调试的时候,会需要安装很多插件,但通过vscode之间安装的话,会出现如下的错误: Installing github.com/mdemp ...

  3. nginx配置后端映射(反向代理proxy_pass)

    说明:配置反向代理proxy_pass和location无关,location后面加不加 / 都可以 1.配置 proxy_pass 时,当在后面的 url 加上了 /,相当于是绝对路径,则 Ngin ...

  4. Divide by Zero 2021 and Codeforces Round #714 (Div. 2) B. AND Sequences思维,位运算 难度1400

    题目链接: Problem - B - Codeforces 题目 Example input 4 3 1 1 1 5 1 2 3 4 5 5 0 2 0 3 0 4 1 3 5 1 output 6 ...

  5. Java语言学习day31--8月06日

    今日内容介绍1.正则表达式的定义及使用2.Date类的用法3.Calendar类的用法 ###01正则表达式的概念和作用 * A: 正则表达式的概念和作用 * a: 正则表达式的概述 * 正则表达式也 ...

  6. 2021.08.16 P1078 文化之旅(最短路)

    2021.08.16 P1078 文化之旅(最短路) 题意: n个地,k个信仰,每个地都有自己的信仰,信仰之间会相互排斥,同信仰之间也会相互排斥,有m条路,问从s到t的最短距离是多少? 有一位使者要游 ...

  7. js 前端实现下拉刷新 上拉加载

    效果 css html,body{ height:100%; // 其他界面未设置html 无法监听scroll } /* 下拉刷新 */ .refresh-loading { transition: ...

  8. javase集合 温故而知新

    复习javase集合 1.为什么要有集合? 数组长度需要在初始化时确定大小,数据结构单一.因此集合出现了 2.数组和集合的区别 区别一:数组既可以存储基本数据类型,又可以存储引用类型,集合只能存储引用 ...

  9. [题解] 51 nod 1340 地铁环线

    不难看出这是一道差分约束的题目. 但是如果想按照通常的题目那样去建边的话,就会发现这句话--相邻两站的距离至少是1公里--建边后就直接让整个题出现了负环(默认是按求最短路建边),没法做了. 这时我们就 ...

  10. 从防御者视角来看APT攻击

    前言 APT防御的重要性毋庸讳言,为了帮助各位师傅在防御方面建立一个总体认识,本文会将APT防御方法分为三类,分别是:监控.检测和缓解技术,并分别进行梳理,介绍分析代表性技术.这一篇分析现有的监控技术 ...