Search code examples
javaspringinversion-of-control

How to properly destroy a Spring configuration class


Case 1

Let's consider the following Spring configuration:

@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());
    } 

 }

For some reasons, I need to invoke a Foo's method (i.e. myFoo.shutdown();) when MyConf1 is destroyed. Is there any way to perform this operation without retrieving the bean instance directly from the application context (via ApplicationContext.getBean())?

Case 2

Again, let's consider a second Spring configuration class:

@Configuration
public class MyConf2 {

    @Bean
    public ScheduledJob scheduledJob() {
        Timer jobTimer = new Timer(true);
        return new ScheduledJob(jobTimer);
    }

 }

This time, I need to invoke jobTimer.cancel() before destroying MyConf2. Indeed, I can instantiate jobTimer outside scheduledJob(), or making it a method's parameter, as scheduledJob(Timer jobTimer). It will then be possible to define a proper destroyer method for MyConf2. However, I would like to know if there are other ways to proceed.

Any good suggestion?

Note: Foo, Bar, Timer, ScheduledJob classes are defined externally. Thus, there is no possibility to explicitly define an inner destroy method. As assumption, I can modify only MyConf1 and MyConf2.


Solution

  • I would suggest defining a destroy() method (annotated with @PreDestroy) in Foo class

    Similarly, modify ScheduledJob class like

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

    And add destroyMethod param in @Bean

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