Spring第三天(Bean生命周期)

发布时间:2024年01月15日

Bean生命周期

生命周期:从创建到销毁的完整过程

Bean生命周期:Bean从创建到销毁的整体过程

Bean生命周期控制:在Bean创建后到销毁前做的事情

Bean生命周期的控制可视化

先写一个简单的Bean控制Dao

<bean id="bookDao" class="com.cacb.dao.impl.BookDaoImpl"/>

在bookdao中写一个save方法来调用

(impl文件内容)

    @Override
    public void save(){
        System.out.println("Dao saving!");
    }

基本配置完成,下面进入可视化部分

既然生命周期的关键就在于Bean的创建销毁

那我们不妨给其设置init()destory()两个方法,在Bean创建销毁的时候调用这两个方法来证明这两个事件的发生

    public void init(){
        System.out.println("bookdao init!");
    }
    public void destory(){
        System.out.println("bookdao destory!");
    }

当然,仅仅写出这两个方法是无法让虚拟机知道该在什么时候调用这两个方法的,所以我们需要修改一下Bean的配置

    <bean id="bookDao" class="com.cacb.dao.impl.BookDaoImpl" init-method="init" destroy-method="destory"/>

意思简单明了,记不住全拼多按几下TAB即可,不多做赘述

但是 我们会发现输出结果只有:

destory方法的输出结果呢?

究其原因,我们的程序自始至终是运行在JAVA虚拟机上的

当虚拟机启动时,IoC容器加载配置一并启动

测试程序从容器中拿取到了Bean

执行了我们调用的save方法,

至此程序执行完毕,虚拟机退出

并没有给其机会来销毁Bean。

所以,想要看到Bean的销毁,我们需要需要使用一定的手段

Bean销毁的可视化方法

方法有二

其一、在虚拟机退出之前关闭容器

? ? ? ? 先看我们的测试程序:

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

怎么操作?,在save后调用容器的close()方法来关闭容器

ctx.close();

但我们发现ApplicationContext接口中不具备close方法,查询ApplicationContext接口的继承关系之后,我们会发现close()方法实在ApplicationContext接口的一个继承接口中书写的,所以我们干脆修改代码,直接将ctx定义为ClassPathXmlApplicationContext类型,就可以直接调用close()方法了

修改后代码:

(非常好从IDEA复制代码,使我的IDEA继每日一崩MAVEN之后又卡死了一次)

(很好,电脑也死机了一次)

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

再运行测试程序,得到结果如下

可以看到destory方法确实被调用

但是,使用close方法来关闭容器是较为暴力的方法,所以引入下一方法

其二、设置关闭钩子
ctx.registerShutdownHook();

给ctx容器设置一个关闭钩子,告诉虚拟机需要在关闭之前关闭管道

运行结果如下:

?

可以看到,两种方法所实现的最终效果是一致的,但是其二者还是有去别的

两种方法的区别

????????close方法较为暴力,必须在程序完成所有有关bean的操作后再调用,否则书写在close后的有关内容不会被运行

????????而关闭钩子可以在管道构建好以后的任何位置书写,虚拟机会在运行完程序的所有代码后再关闭管道

那么在实际应用中应该选用哪种方法呢?

实际上在实际应用中我们都是在开发web程序,关闭管道交由tomcat完成,这两种方法我们都是用不上的,在此只作为学习Bean生命周期的知识点出现!

生命周期控制方法的进一步(实现Spring接口)

在这种方法中,要实现Bean生命周期的控制,我们需要继承Spring提供的两个接口

InitializingBeanDisposableBean

继承这两个接口后,我们还要覆写接口中的两个方法:

    @Override
    public void destroy() throws Exception {

    }

    @Override
    public void afterPropertiesSet() throws Exception {

    }

我们用serviceimpl来dao来区分两种控制方法的实现

public class BookServiceSImpl implements BookService, InitializingBean, DisposableBean {
    private BookDao bookDao;
    @Override
    public void save(){
        System.out.println("Service saving!");
    }

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

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

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

dao代码见前一种控制方法

调用测试程序,

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

获得结果:

可以看到,虽然我们没有调用sevice,但是由于doa和service存于同一个管道中,service也会被加载,所以也能看到service的创建和销毁

文章来源:https://blog.csdn.net/Cary_cacb/article/details/135586159
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。