内容:
- 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创建之前先创建好,销毁顺序刚好相反