Caso 1

Consideremos la siguiente configuración de 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());
    } 

 }

Por alguna razón, necesito invocar el método de Foo (es decir, myFoo.shutdown();) cuando se destruye MyConf1. ¿Hay alguna forma de realizar esta operación sin recuperar la instancia de bean directamente del contexto de la aplicación (a través de ApplicationContext.getBean())?

Caso 2

Nuevamente, consideremos una segunda clase de configuración de Spring:

@Configuration
public class MyConf2 {

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

 }

Esta vez, necesito invocar jobTimer.cancel() antes de destruir MyConf2. De hecho, puedo crear instancias jobTimer fuera de scheduledJob(), o convertirlo en un parámetro de método, como scheduledJob(Timer jobTimer). Entonces será posible definir un método destructor adecuado para MyConf2. Sin embargo, me gustaría saber si hay otras formas de proceder.

Alguna buena sugerencia?

Nota: las clases Foo, Bar, Timer, ScheduledJob se definen externamente. Por lo tanto, no hay posibilidad de definir explícitamente un método interno de destrucción. Como supuesto, solo puedo modificar MyConf1 y MyConf2.

3
vdenotaris 24 jun. 2017 a las 12:45

3 respuestas

La mejor respuesta

Sugeriría definir un método destroy() (anotado con @PreDestroy) en la clase Foo

Del mismo modo, modifique la clase ScheduledJob como

public class ScheduledJob {

    private Timer timer;

    public ScheduledJob(Timer timer){
        this.timer = timer;
    }

    @PreDestroy
    public void destroy(){
        timer.cancel();
    }
}

Y agregue destroyMethod param en @Bean

@Configuration
public class MyConf2 {

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

}
4
Archit 24 jun. 2017 a las 10:26

Consulte la siguiente página http: / /forum.spring.io/forum/spring-projects/container/48426-postconstruct-and-predestroy-in-javaconfig

DisposableBean debería ayudarlo con el caso # 1.

0
Florian S. 24 jun. 2017 a las 10:05

Puede implementar la interfaz DestructionAwareBeanPostProcessor que puede agregar una devolución de llamada antes de la destrucción cuando el bean se destruye. En esa interfaz, el método postProcessBeforeDestruction es hacer eso, consulte lo siguiente:

@Override
public void postProcessBeforeDestruction(Object bean, String beanName) throws BeansException {
    System.out.println("before destory:"+bean);
}

@Override
public boolean requiresDestruction(Object bean) {
    return true;
}

Preste atención a que el método requiresDestruction debe devolver verdadero, de lo contrario el método postProcessBeforeDestruction no llamará cuando el bean debería destruir.

Y tengo una prueba:

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

El postProcessBeforeDestruction realmente llama cuando el bean se destruye. La salida es:

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
0
dabaicai 24 jun. 2017 a las 11:00