如何正确销毁 Spring 配置 class
How to properly destroy a Spring configuration class
案例一
让我们考虑以下 Spring 配置:
@Configuration
public class MyConf1 {
@Bean
public Foo getFoo() {
// Foo class is defined as part of an external lib.
return new Foo();
}
@Bean
public Bar getBar() {
return new Bar(getFoo());
}
}
出于某些原因,我需要在 MyConf1
被销毁时调用 Foo
的方法(即 myFoo.shutdown();
)。
有什么方法可以在不直接从应用程序上下文(通过 ApplicationContext.getBean()
)检索 bean 实例的情况下执行此操作?
案例二
同样,让我们考虑第二个 Spring 配置 class:
@Configuration
public class MyConf2 {
@Bean
public ScheduledJob scheduledJob() {
Timer jobTimer = new Timer(true);
return new ScheduledJob(jobTimer);
}
}
这一次,我需要在销毁MyConf2
之前调用jobTimer.cancel()
。实际上,我可以在 scheduledJob()
之外实例化 jobTimer
,或者将其作为方法的参数,如 scheduledJob(Timer jobTimer)
。
然后就可以为 MyConf2
定义一个合适的破坏者方法。但是,我想知道是否还有其他方法可以继续。
有什么好的建议吗?
注:Foo
、Bar
、Timer
、ScheduledJob
class都是外部定义的。因此,不可能显式定义内部销毁方法。作为假设,我只能修改 MyConf1
和 MyConf2
。
DisposableBean 应该可以帮助您解决案例 #1。
我建议在 Foo
class
中定义一个 destroy()
方法(用 @PreDestroy
注释)
类似地,将ScheduledJob
class修改为
public class ScheduledJob {
private Timer timer;
public ScheduledJob(Timer timer){
this.timer = timer;
}
@PreDestroy
public void destroy(){
timer.cancel();
}
}
并在@Bean
中添加destroyMethod
参数
@Configuration
public class MyConf2 {
@Bean(destroyMethod = "destroy")
public ScheduledJob scheduledJob() {
Timer jobTimer = new Timer(true);
return new ScheduledJob(jobTimer);
}
}
你可以实现DestructionAwareBeanPostProcessor
接口,当bean是destroy.In那个接口时,可以添加一个销毁前的回调,方法postProcessBeforeDestruction
就是这样做的,看下面:
@Override
public void postProcessBeforeDestruction(Object bean, String beanName) throws BeansException {
System.out.println("before destory:"+bean);
}
@Override
public boolean requiresDestruction(Object bean) {
return true;
}
注意方法requiresDestruction
必须return为真,否则bean应该销毁时方法postProcessBeforeDestruction
不会调用
我有一个测试:
public static void main(String[] args){
ClassPathXmlApplicationContext applicationContext=new ClassPathXmlApplicationContext("classpath:application-main.xml");
applicationContext.registerShutdownHook();
}
当 bean 为 destroy.The 时真正调用 postProcessBeforeDestruction
输出为:
before destory:com.zhuyiren.spring.learn.util.Handler@55141def
before destory:com.zhuyiren.spring.learn.controller.TestControleler@47eaca72
before destory:com.zhuyiren.spring.learn.service.impl.TestServiceImpl@7b2bbc3
before destory:com.zhuyiren.spring.learn.service.impl.TwoServiceImpl@48f2bd5b
before destory:com.zhuyiren.spring.learn.controller.ConverConroller@72967906
before destory:org.springframework.context.event.DefaultEventListenerFactory@1a482e36
before destory:org.springframework.context.event.EventListenerMethodProcessor@77fbd92c
案例一
让我们考虑以下 Spring 配置:
@Configuration
public class MyConf1 {
@Bean
public Foo getFoo() {
// Foo class is defined as part of an external lib.
return new Foo();
}
@Bean
public Bar getBar() {
return new Bar(getFoo());
}
}
出于某些原因,我需要在 MyConf1
被销毁时调用 Foo
的方法(即 myFoo.shutdown();
)。
有什么方法可以在不直接从应用程序上下文(通过 ApplicationContext.getBean()
)检索 bean 实例的情况下执行此操作?
案例二
同样,让我们考虑第二个 Spring 配置 class:
@Configuration
public class MyConf2 {
@Bean
public ScheduledJob scheduledJob() {
Timer jobTimer = new Timer(true);
return new ScheduledJob(jobTimer);
}
}
这一次,我需要在销毁MyConf2
之前调用jobTimer.cancel()
。实际上,我可以在 scheduledJob()
之外实例化 jobTimer
,或者将其作为方法的参数,如 scheduledJob(Timer jobTimer)
。
然后就可以为 MyConf2
定义一个合适的破坏者方法。但是,我想知道是否还有其他方法可以继续。
有什么好的建议吗?
注:Foo
、Bar
、Timer
、ScheduledJob
class都是外部定义的。因此,不可能显式定义内部销毁方法。作为假设,我只能修改 MyConf1
和 MyConf2
。
DisposableBean 应该可以帮助您解决案例 #1。
我建议在 Foo
class
destroy()
方法(用 @PreDestroy
注释)
类似地,将ScheduledJob
class修改为
public class ScheduledJob {
private Timer timer;
public ScheduledJob(Timer timer){
this.timer = timer;
}
@PreDestroy
public void destroy(){
timer.cancel();
}
}
并在@Bean
destroyMethod
参数
@Configuration
public class MyConf2 {
@Bean(destroyMethod = "destroy")
public ScheduledJob scheduledJob() {
Timer jobTimer = new Timer(true);
return new ScheduledJob(jobTimer);
}
}
你可以实现DestructionAwareBeanPostProcessor
接口,当bean是destroy.In那个接口时,可以添加一个销毁前的回调,方法postProcessBeforeDestruction
就是这样做的,看下面:
@Override
public void postProcessBeforeDestruction(Object bean, String beanName) throws BeansException {
System.out.println("before destory:"+bean);
}
@Override
public boolean requiresDestruction(Object bean) {
return true;
}
注意方法requiresDestruction
必须return为真,否则bean应该销毁时方法postProcessBeforeDestruction
不会调用
我有一个测试:
public static void main(String[] args){
ClassPathXmlApplicationContext applicationContext=new ClassPathXmlApplicationContext("classpath:application-main.xml");
applicationContext.registerShutdownHook();
}
当 bean 为 destroy.The 时真正调用 postProcessBeforeDestruction
输出为:
before destory:com.zhuyiren.spring.learn.util.Handler@55141def
before destory:com.zhuyiren.spring.learn.controller.TestControleler@47eaca72
before destory:com.zhuyiren.spring.learn.service.impl.TestServiceImpl@7b2bbc3
before destory:com.zhuyiren.spring.learn.service.impl.TwoServiceImpl@48f2bd5b
before destory:com.zhuyiren.spring.learn.controller.ConverConroller@72967906
before destory:org.springframework.context.event.DefaultEventListenerFactory@1a482e36
before destory:org.springframework.context.event.EventListenerMethodProcessor@77fbd92c