夯实spring(九):bean的创建和销毁的顺序和depends-on

内容:

  • bean的创建和销毁的顺序
  • 如何干预bean的创建和销毁的顺序
  • depends-on的使用

1,没有依赖的bean创建和销毁的顺序

创建一个例子看看没有任何依赖的bean的创建和销毁的顺序

public class Bean1 implements DisposableBean {

    public Bean1() {
        System.out.println(this.getClass() + " constructor!");
    }

    @Override
    public void destroy() throws Exception {
        System.out.println(this.getClass() + " destroy()");
    }
}
public class Bean2 implements DisposableBean {
    public Bean2() {
        System.out.println(this.getClass() + " constructor!");
    }

    @Override
    public void destroy() throws Exception {
        System.out.println(this.getClass() + " destroy()");
    }
}
public class Bean3 implements DisposableBean {
    public Bean3() {
        System.out.println(this.getClass() + " constructor!");
    }

    @Override
    public void destroy() throws Exception {
        System.out.println(this.getClass() + " destroy()");
    }
}

上面使用到了DisposableBean接口,这个是spring容器提供的一个接口,这个接口中有个destroy方法,我们的bean类可以实现这个接口,当我们调用容器的close方法关闭容器的时候,spring会调用容器中所有bean的destory方法,用来做一些清理的工作。上面3个类中构造方法和destory方法中都有输出。

bean.xml

<?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-4.3.xsd">

    <bean id="bean3" class="com.chen.Bean3"></bean>
    <bean id="bean2" class="com.chen.Bean2"></bean>
    <bean id="bean1" class="com.chen.Bean1"></bean>
</beans>

上面xml中bean定义顺序是:bean3、bean2、bean1。

搞个测试类,看看创建和销毁的顺序

public class Main {
    public static void main(String[] args) {
        System.out.println("容器启动");
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("classpath:bean.xml");
        System.out.println("容器启动完毕,准备关闭spring容器!");
        //关闭容器
        context.close();
        System.out.println("spring容器已关闭!");
    }
}
容器启动
class com.chen.Bean3 constructor!
class com.chen.Bean2 constructor!
class com.chen.Bean1 constructor!
容器启动完毕,准备关闭spring容器!
class com.chen.Bean1 destroy()
class com.chen.Bean2 destroy()
class com.chen.Bean3 destroy()
spring容器已关闭!

输出结果可以看到:

bean定义顺序	        创建顺序	          销毁顺序
bean3	            bean3	           bean1
bean2	            bean2	           bean2
bean1	            bean1	           bean3

小结:

  • bean对象的创建顺序和bean.xml中定义的顺序一致
  • bean销毁的顺序和bean.xml中定义的顺序相反

2,通过构造器添加强依赖的bean创建和销毁顺序

案例改造一下,通过构造函数注入的方式使bean之间产生强依赖。

public class Bean1 implements DisposableBean {

    public Bean1() {
        System.out.println(this.getClass() + " constructor!");
    }

    @Override
    public void destroy() throws Exception {
        System.out.println(this.getClass() + " destroy()");
    }
}
public class Bean2 implements DisposableBean {
    private Bean1 bean1;

    public Bean2(Bean1 bean1) {
        this.bean1 = bean1;
        System.out.println(this.getClass() + " constructor!");
    }

    @Override
    public void destroy() throws Exception {
        System.out.println(this.getClass() + " destroy()");
    }
}
public class Bean3 implements DisposableBean {
    private Bean2 bean2;

    public Bean3(Bean2 bean2) {
        this.bean2 = bean2;
        System.out.println(this.getClass() + " constructor!");
    }

    @Override
    public void destroy() throws Exception {
        System.out.println(this.getClass() + " destroy()");
    }
}
  • 创建Bean2的时候需要传入一个bean1对象,对bean1产生了强依赖
  • 创建Bean3的时候需要传入一个bean2对象,对bean2产生了强依赖

bean.xml

<?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-4.3.xsd">

    <bean id="bean3" class="com.chen.Bean3">
        <constructor-arg index="0" ref="bean2"/>
    </bean>
    
    <bean id="bean2" class="com.chen.Bean2">
        <constructor-arg index="0" ref="bean1"/>
    </bean>
    
    <bean id="bean1" class="com.chen.Bean1"></bean>
</beans>

测试输出

public class Main {
    public static void main(String[] args) {
        System.out.println("容器启动");
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("classpath:bean.xml");
        System.out.println("容器启动完毕,准备关闭spring容器!");
        //关闭容器
        context.close();
        System.out.println("spring容器已关闭!");
    }
}
容器启动
class com.chen.Bean1 constructor!
class com.chen.Bean2 constructor!
class com.chen.Bean3 constructor!
容器启动完毕,准备关闭spring容器!
class com.chen.Bean3 destroy()
class com.chen.Bean2 destroy()
class com.chen.Bean1 destroy()
spring容器已关闭!

结果可以看到:

bean定义顺序	   依赖顺序(下面依赖上面的)	 创建顺序	   销毁顺序
bean3	            bean1	              bean1	        bean3
bean2	            bean2	              bean2	        bean2
bean1	            bean3	              bean3	        bean1

小结:

  • bean对象的创建顺序和bean依赖的顺序一致,被依赖的bean先创建。
  • bean销毁的顺序和bean创建的顺序相反,被依赖的bean后销毁。

3,通过depend-on干预bean创建和销毁顺序

上面看到了对于无依赖的bean,通过定义的顺序确实可以干预bean的创建顺序,通过强依赖也可以干预bean的创建顺序。

那么如果xml中定义的bean特别多,而有些bean之间也没有强依赖关系,此时如果想去调整bean的创建和销毁的顺序,得去调整xml中bean的定义顺序,或者去加强依赖,这样是非常不好的,spring中可以通过depend-on来解决这些问题,在不调整bean的定义顺序和强加依赖的情况下,可以通过通过depend-on属性来设置当前bean的依赖于哪些bean,那么可以保证depend-on指定的bean在当前bean之前先创建好,销毁的时候在当前bean之后进行销毁。

<bean id="bean1" class="" depend-on="bean2,bean3; bean4" />

depend-on:设置当前bean依赖的bean名称,可以指定多个,多个之间可以用“ , ; 空格”进行分割
上面不管bean2,bean3,bean4在任何地方定义,都可以确保在bean1创建之前,会先将bean2,bean3,bean4创建好,表示bean1依赖于这3个bean,可能bean1需要用到bean2、bean3、bean4中生成的一些资源或者其他的功能等,但是又没有强制去在bean1类中通过属性定义强依赖的方式去依赖于bean2、bean3、bean4;当然销毁的时候也会先销毁当前bean,再去销毁被依赖的bean,即先销毁bean1,再去销毁depend-on指定的bean。

案例:
bean1,bean2,bean3使用案例1的。

bean.xml

<?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-4.3.xsd">

    <bean id="bean1" class="com.chen.Bean1" depends-on="bean2 bean3"></bean>

    <bean id="bean3" class="com.chen.Bean3"></bean>

    <bean id="bean2" class="com.chen.Bean2"></bean>

</beans>

测试输出:

public class Main {
    public static void main(String[] args) {
        System.out.println("容器启动");
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("classpath:bean.xml");
        System.out.println("容器启动完毕,准备关闭spring容器!");
        //关闭容器
        context.close();
        System.out.println("spring容器已关闭!");
    }
}

容器启动
class com.chen.Bean2 constructor!
class com.chen.Bean3 constructor!
class com.chen.Bean1 constructor!
容器启动完毕,准备关闭spring容器!
class com.chen.Bean1 destroy()
class com.chen.Bean3 destroy()
class com.chen.Bean2 destroy()
spring容器已关闭!

总结:

  • 无依赖的bean创建顺序和定义的顺序一致,销毁顺序刚好相反
  • 通过构造器强依赖的bean,会先创建构造器参数中对应的bean,然后才会创建当前bean,销毁顺序刚好相反
  • depend-on可以指定当前bean依赖的bean,通过这个可以确保depend-on指定的bean在当前bean创建之前先创建好,销毁顺序刚好相反
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值