自定义Bean的性质
-
生命周期回调
1.1 初始化回调
如果我们的Bean实现
The org.springframework.beans.factory.InitializingBean接口,当容器将所有必要的属性注入该bean之后,我们实现的afterPropertiesSet()方法将会被回调。<bean id="exampleInitBean" class="examples.AnotherExampleBean"/>public class AnotherExampleBean implements InitializingBean { @Override public void afterPropertiesSet() { // do some initialization work } }但是这样做就将业务代码与Spring框架耦合了。
在基于XML的配置中,为
<bean>元素的init-method属性指定一个初始化方法,可以起到相同的效果。<bean id="exampleInitBean" class="examples.ExampleBean" init-method="init"/>public class ExampleBean { public void init() { // do some initialization work } }在基于注解的配置中,使用
@PostConstruct对初始化方法进行注解:@Bean public class ExampleBean { @PostConstruct public void init() { // do some initialization work } }1.2 销毁回调
如我们的bean实现了
org.springframework.beans.factory.DisposableBean接口,当管理该bean的容器被销毁后,我们实现的destroy()方法将会被回调。<bean id="exampleInitBean" class="examples.AnotherExampleBean"/>public class AnotherExampleBean implements DisposableBean { @Override public void destroy() { // do some destruction work (like releasing pooled connections) } }但是这与Spring框架耦合了。
在基于XML的配置中,为
<bean>元素的destroy-method属性指定一个销毁方法,可以起到相同的效果。<bean id="exampleInitBean" class="examples.ExampleBean" destroy-method="cleanup"/>public class ExampleBean { public void cleanup() { // do some destruction work (like releasing pooled connections) } }在基于注解的配置中,使用
@PreDestroy:@Bean public class ExampleBean { @PreDestroy public void init() { // do some initialization work } }1.3 默认初始化和销毁方法
如果在整个项目中,都使用相同的名称为bean定义初始化和销毁方法,那么我们就可以配置默认的初始化和销毁回调方法名。
<beans defualt-init-method="init" defualt-destroy-method="cleanup"> <bean id="blogService" class="com.something.DefaultBlogService"> <property name="blogDao" ref="blogDao" /> </bean> </beans>public class DefaultBlogService implements BlogService { private BlogDao blogDao; public void setBlogDao(BlogDao blogDao) { this.blogDao = blogDao; } // this is (unsurprisingly) the initialization callback method public void init() { if (this.blogDao == null) { throw new IllegalStateException("The [blogDao] property must be set."); } } }1.4 联合生命周期机制(多种配置方式混用)
我们可以同时使用多种方式来定义bean的生命周期回调,如果每种方式对应不同的方法,那么这些方法将按下面的顺序回调。
初始化方法:
- 被
@PostConstruct注解的方法 - 实现
InitializingBean接口的afterPropertiesSet方法 - XML中
<bean>元素的init-method指定的方法
销毁方法: - 被
@PreDestroy注解的方法 - 实现
DisposableBean接口的destroy方法 - XML中
<bean>元素的destroy-method指定的方法
1.5 ·Startup和Shutdown回调
org.springframework.context.Lifycycle接口为任意有自己生命周期的对象定义了重要的方法:public interface Lifecycle{ void start(); void stop(); boolean isRunning(); }任何被容器管理的对象都可以继承这个接口,当容器接收到
start和stop信号后,会将这个调用传递给实现这个接口的对象。org.springframework.context.Lifecycle接口只是对start和stop通知的简单定义,它并不会在容器刷新是自动启动,我们应该实现org.springframework.context.SmartLifecyclepublic interface Phased { int getPhase(); } public interface SmartLifecycle extends Lifecycle, Phased { boolean isAutoStartup(); void stop(Runnable callback); }当我们实现
SmartLifecycle接口的isAutoStartup方法时,如果返回true,那么在容器刷新时,就会自动调用start方法(Lifecycle的实现);如果返回false,那么就只有显示调用这个方法,或者调用容器的start方法时自动回调bean的start方法。Phased接口的getPhase方法的返回值将决定哪个bean的start方法先被调用。phase值越小,越先调用start,越后调用stop(Runnable);普通bean(没有继承Lifecycle接口的bean)phase默认为0。下面是一个简单的例子:
public class MyTask implements SmartLifecycle { public static final Logger log = Logger.getLogger("com.heisenberg.spring"); Thread t; boolean isRunning = false; public void start() { MyRunnable runnable = new MyRunnable(); t = new Thread(runnable); t.start(); if (!t.isInterrupted()){ log.info(Utils.LOG_TAG + "Task is Running"+Utils.LOG_TAG); isRunning = true; } } public void stop() { t.interrupt(); } public boolean isRunning() { return isRunning; } public boolean isAutoStartup() { return false; } public void stop(Runnable callback) { this.stop(); if (t.isInterrupted()){ log.info(Utils.LOG_TAG + "Task stopped"+Utils.LOG_TAG); } callback.run(); } public int getPhase() { return -1; } } class MyRunnable implements Runnable{ public static final Logger log = Logger.getLogger("com.heisenberg.spring"); public void run() { while (!Thread.currentThread().isInterrupted()){ log.info(Utils.LOG_TAG + "Tick" + Utils.LOG_TAG); } } }1.6 在非Web应用中优雅的关闭容器
public static void main(String[] args){ //使用AbstractApplicationContext或者ConfigurableApplicationContext都可以 //AbstractApplicationContext context = new ClassPathXmlApplicationContext("service.xml"); ConfigurableApplicationContext context = new ClassPathXmlApplicationContext("service.xml"); //在JVM中注册一个关闭钩子 context.registerShutdownHook(); //下面是任务 //当任务完成后退出应用,在退出之前退出钩子会被回调,它将关闭容器 System.exit(0) } - 被
-
ApplicationContextAware和BeanNameAware2.1
ApplicationContextAware当一个
ApplicationContext容器创建了一个实现了ApplicationContextAware接口的类实例时,这个实例将拥有它所在容器的引用。但是并不推荐实现
ApplicationContextAware接口,这会使代码跟Spring耦合,这也违背了控制反转的风格。我们也可以通过自动装配来获取容器的引用
2.2
BeanNameAware当一个类实现了
BeanNameAware接口,容器创建这个类的实例之后,该bean将会得到一个名称的引用。这个名称是其它bean对这个bean的引用的变量名称。public interface BeanNameAware { //name 便是其它bean对该bean的引用变量名 void setBeanName(String name) throws BeansException; } -
其它的
Aware接口
其它的Aware接口
本文详细探讨了Spring框架中Bean的生命周期,包括初始化和销毁的多种回调机制,如@PostConstruct、InitializingBean接口、XML init-method等。同时,介绍了如何通过SmartLifecycle接口实现自定义的启动和关闭回调。

被折叠的 条评论
为什么被折叠?



