[Spring Framework]bean的生命周期以及控制

举报
十八岁讨厌编程 发表于 2022/08/06 22:32:37 2022/08/06
【摘要】 文章目录 bean的生命周期控制(配置文件法)容器的关闭bean的生命周期控制(实现接口法)总结 bean的生命周期控制(配置文件法) bean的生命周期就是bean对象从创建到销毁的整体...

bean的生命周期控制(配置文件法)

bean的生命周期就是bean对象从创建到销毁的整体过程。

我们在bean的生命周期中可以干一些事情(也就是对他的生命周期进行一些控制),例如创建之后(比如用来初始化需要用到资源),销毁之前(比如用来释放用到的资源)。

接下来我们进行尝试:

首先项目背景:

有一个实现了BookDao接口的是实现类BookDaoImpl:

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

  
 
  • 1
  • 2
  • 3
  • 4
  • 5

我们把它放到IOC容器中:

<bean id="bookDao" name="bookBookDao" class="impl.BookDaoImpl"/>

  
 
  • 1

接下来我们就以这个实现类BookDaoImpl为例子:

首先我们在实现类BookDaoImpl中编写两个方法,分别对应着初始化方法、销毁方法:

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...");
    }
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

注意这两个方法不能有返回值,不要有参数!

然后我们在Spring的配置文件中对他们进行配置,是他们真正的成为生命周期的控制方法:

<bean id="bookDao" name="bookBookDao" class="impl.BookDaoImpl" init-method="init" destroy-method="destory"/>

  
 
  • 1
  • init-method来配置初始化方法
  • destroy-method来配置销毁方法

这样就完成了,接下来我们运行程序:

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

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

结果为:
在这里插入图片描述

我们发现销毁方法并没有执行,这是为什么呢?

Spring的IOC容器是运行在JVM中,运行main方法后,JVM启动,Spring加载配置文件生成IOC容器,从容器获取bean对象,然后调方法执行,main方法执行完后,JVM退出,这个时候IOC容器中的bean还没有来得及销毁就已经结束了,所以没有调用对应的destroy方法。

容器的关闭

如果我们想要销毁方法生效,那么我们就要在jvm关闭之前就把IOC容器进行关闭,而这里关闭IOC容器有两种方式:

  • close关闭容器
  • 注册钩子关闭容器

首先我们说说如何使用close关闭容器。要想使用close方法,那么得先有close方法:
在这里插入图片描述
close方法是从ConfigurableApplicationContext接口之后才开始有的,也就是说如果你写成如下是调用不了close方法的:

ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");

  
 
  • 1

如上是一个注意点,好在我们的代码是没有这种问题的:
在这里插入图片描述
然后调用close方法即可:

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

    }
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

结果:

在这里插入图片描述

然后我们再注册钩子关闭容器,

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

  • 调用ctx的registerShutdownHook()方法

    ctx.registerShutdownHook();
    
        
       
    • 1

注意:registerShutdownHook在ApplicationContext中也没有

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

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

结果:
在这里插入图片描述

这两种关闭方法的区别在于:close()是在调用的时候关闭,registerShutdownHook()是在JVM退出前调用关闭。

bean的生命周期控制(实现接口法)

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

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

我们接下来进行试验:

添加项目背景:

现在有一个实现了BookService接口的BookServiceImpl类,它依赖于BookDao:

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();
    }
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

我们以他为例子,首先实现两个接口InitializingBeanDisposableBean并实现接口中的两个方法afterPropertiesSetdestroy

public class BookServiceImpl implements BookService, DisposableBean, InitializingBean {
    private BookDao bookDao;

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

    public void destroy() throws Exception {
        System.out.println("service destroy");
    }

    public void afterPropertiesSet() throws Exception {
        System.out.println("service init");
    }

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

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

在配置文件中,我们可以不使用那两个配置项:

	<bean id="bookDao" name="bookBookDao" class="impl.BookDaoImpl" init-method="init" destroy-method="destory"/>
    <bean id="bookService" class="impl.BookServiceImpl" scope="prototype">
        <property name="bookDao" ref="bookBookDao"></property>
    </bean>

  
 
  • 1
  • 2
  • 3
  • 4

执行结果:
在这里插入图片描述
还有一个注意点:

对于InitializingBean接口中的afterPropertiesSet方法,翻译过来为属性设置之后。对于BookServiceImpl来说,bookDao是它的一个属性。setBookDao方法是Spring的IOC容器为其注入属性的方法。setBookDao应该在afterPropertiesSet之前执行。推广一下初始化方法会在类中属性设置之后执行。

我们实验一下:

在setBookDao中添加一个打印语句:

public class BookServiceImpl implements BookService, DisposableBean, InitializingBean {
    private BookDao bookDao;

    public void setBookDao(BookDao bookDao) {
        System.out.println("set property....");
        this.bookDao = bookDao;
    }

    public void destroy() throws Exception {
        System.out.println("service destroy");
    }

    public void afterPropertiesSet() throws Exception {
        System.out.println("service init");
    }

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

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

然后我们再执行,结果如下:
在这里插入图片描述

总结

(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()方法

文章来源: blog.csdn.net,作者:十八岁讨厌编程,版权归原作者所有,如需转载,请联系作者。

原文链接:blog.csdn.net/zyb18507175502/article/details/125731358

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。