有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java如何正确销毁Spring配置类

案例1

让我们考虑下面的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();)。 有没有办法在不直接从应用程序上下文检索bean实例的情况下执行此操作(通过ApplicationContext.getBean()

案例2

再次,让我们考虑第二个Spring配置类:

@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定义一个合适的销毁程序方法。不过,我想知道是否还有其他方法可以进行

有什么好建议吗

注意:FooBarTimerScheduledJob类是外部定义的。因此,不可能明确定义内部销毁方法。作为假设,我只能修改MyConf1MyConf2


共 (3) 个答案

  1. # 1 楼答案

    您可以实现DestructionAwareBeanPostProcessor接口,该接口可以在bean被销毁时添加销毁前回调。在该接口中,方法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应该返回true,否则当bean应该销毁时方法postProcessBeforeDestruction将不会调用

    我有个测试:

    public static void main(String[] args){
        ClassPathXmlApplicationContext applicationContext=new ClassPathXmlApplicationContext("classpath:application-main.xml");
        applicationContext.registerShutdownHook();
    }
    

    当bean被销毁时,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
    
  2. # 3 楼答案

    我建议在Foo类中定义destroy()方法(用@PreDestroy注释)

    类似地,修改ScheduledJob

    public class ScheduledJob {
    
        private Timer timer;
    
        public ScheduledJob(Timer timer){
            this.timer = timer;
        }
    
        @PreDestroy
        public void destroy(){
            timer.cancel();
        }
    }
    

    并在@Bean中添加destroyMethodparam

    @Configuration
    public class MyConf2 {
    
        @Bean(destroyMethod = "destroy")
        public ScheduledJob scheduledJob() {
            Timer jobTimer = new Timer(true);
            return new ScheduledJob(jobTimer);
        }
    
    }