Spring能够管理singleton做用域Bean的生命周期,Spring能够精确的知道该Bean什么时候被建立、什么时候被初始化完成、容器什么时候准备销毁该Bean实列。java
对于prototype做用域的Bean,Spring容器仅负责建立,当容器建立了Bean实列以后,Bean实列彻底交给客户端代码管理,容器再也不跟踪其生命周期。spring
对于singleton做用域的Bean,Spring容器知道Bean什么时候实列化结束、什么时候销毁。Spring能够管理Bean在实列化结束以后和销毁以前的行为。管理Bean的生命周期行为主要有以下两个时机:app
Spring提供两种方式在Bean注入依赖关系后执行特定行为;ide
第一:在xml中配置<bean>时,为其配置init-method属性,该属性指定Bean所有依赖关系设置结束后,自动执行该属性指定的方法;测试
第二:让Bean类实现InitalizingBean接口,该接口提供public void afterPropertiesSet() throws Exception方法。spa
<!--使用init-method指定Bean注入后执行方法--> <bean id="init" class="com.custle.spring.Init" init-method="init"/>
package com.custle.spring; import org.springframework.beans.factory.InitializingBean; /** * Created by admin on 2018/3/1. */ public class Init implements InitializingBean { @Override public void afterPropertiesSet() throws Exception { System.out.println("正在执行初始化方法 afterPropertiesSet()"); } public void init(){ System.out.println("正在使用init-method属性指定初始化方法 init()"); } }
测试程序:prototype
package com.custle.spring; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; /** * Created by admin on 2018/3/1. */ public class BeanFactory { public static void main(String[] args) { ApplicationContext act = new ClassPathXmlApplicationContext("applicationContext-spring.xml"); act.getBean("init"); } }
程序输出:code
正在执行初始化方法 afterPropertiesSet() 正在使用init-method属性指定初始化方法 init()
能够看见,当同时使用这两种方式初始化方法时,先执行InitializingBean接口中定义的方法,而后执行init-method属性指定的方法。使用InitializingBean接口的方式代码耦合性较高。xml
与定制初始化行为类似,Spring也提供了两种方式定制Bean销毁以前的特定行为,这两种方式以下:接口
第一:在xml中配置<bean>时使用destory-method属性;
第二:实现DisposableBean接口;
<!--使用destory-method指定Bean销毁前执行方法--> <bean id="destory" class="com.custle.spring.Destory" destroy-method="close"/>
package com.custle.spring; import org.springframework.beans.factory.DisposableBean; /** * Created by admin on 2018/3/1. */ public class Destory implements DisposableBean { @Override public void destroy() throws Exception { System.out.println("正在经过实现DisposableBean接口执行Bean销毁前的destroy()方法"); } public void close(){ System.out.println("正在经过destory-method执行Bean销毁前的close()方法"); } }
测试程序:
package com.custle.spring; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; /** * Created by admin on 2018/3/1. */ public class BeanFactory { public static void main(String[] args) { ApplicationContext act = new ClassPathXmlApplicationContext("applicationContext-spring.xml"); act.getBean("destory"); } }
控制台输出:
正在使用init-method属性指定初始化方法 init()
能够看见当同时使用这两种方式执行Bean销毁前行为时,只有经过init-method属性配置的方式生效了。这是为何呢?单列Bean的生命周期随着Spring容器的关闭而销毁,若是在一个非WEB应用环境下,为了让Spring容器优雅的关闭,并调用singleton Bean上相应的析构回调方法,则须要在JVM中注册一个关闭钩子,这样就能够保证Spring容器被恰当关闭。
使用以下测试程序:
package com.custle.spring; import org.springframework.context.ApplicationContext; import org.springframework.context.support.AbstractApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; /** * Created by admin on 2018/3/1. */ public class BeanFactory { public static void main(String[] args) { AbstractApplicationContext act = new ClassPathXmlApplicationContext("applicationContext-spring.xml"); act.getBean("destory"); act.registerShutdownHook(); } }
控制台输出:
正在经过实现DisposableBean接口执行Bean销毁前的destroy()方法 正在经过destory-method执行Bean销毁前的close()方法
能够看见当这两种方式同时执行时,经过实现DisposableBean接口执行销毁Bean前的行为优先级更高。
除此以外,若是容器中不少Bean都须要指定特定的生命周期行为,则能够在<beans>中设置default-init-method属性和default-destory-method属性,它们的做用和init-method、destory-method属性相似,只不过它们是对该<beans>下全部的bean都生效。
当Bean实现了ApplicationContextAware接口、BeanNameAware接口以后,Spring容器会在该Bean初始化完成以后--也就是调用init-method属性所指定的方法(若是有)以后,再回调setApplicationConetext(ApplicationContext applicationConext)、setBeanName(String name)方法。