Pramy opened SPR-17456 and commented
I know a bean implement ApplicationListener
will be remove from Context when it destroy,
but ApplicationListenerMethodAdapter
can't be remove
1.ParentContext invoke close method
2.Listener destroy
it did not implements ApplicationListener when use @EventListener
3.NamedContext destroy
it will invoke close method and publish close event, and parentContext will also publish close
event, ApplicationListenerMethodAdapter
working will invoke conetext#getBean
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
ConfigurableApplicationContext context = SpringApplication.run(DemoApplication.class, args);
context.close();
}
class Listener implements DisposableBean {
@EventListener(ContextClosedEvent.class)
public void close(ApplicationEvent event) {
System.out.println("---------------invoke listener"+event );
}
@Override
public void destroy() throws Exception {
System.out.println("--------------------listener destroy-----------------------");
}
}
//1.insure NamedContextFactory initialize before listener
//2.insure NamedContextFactory destroy after listener
@Bean
public Listener listener() {
//3.initialize context values
namedContextFactory().getInstance("demo",DemoApplication.class);
return new Listener();
}
@Bean
public NamedContextFactory<NamedContextFactory.Specification> namedContextFactory() {
return new NamedContextFactory<NamedContextFactory.Specification>(Config.class
,"demo","demo") {};
}
@Configuration
class Config{}
}
Affects: 5.0.9, 5.0.10, 5.1.1, 5.1.2
Reference URL: https://github.com/Pramy/spring-listener-bug
Attachments: - demo.rar (32.98 kB)
Referenced from: pull request https://github.com/spring-projects/spring-framework/pull/2006
Comment From: jhoeller
There is indeed an issue with not clearing the internal ApplicationEventMulticaster
(which may hold on to remaining ApplicationListenerMethodAdapters) on context close. As of 6.1, we reset those internal delegate references to null
on close.
That said, the scenario above closes the contexts in the wrong order: You need to close the child context first, then the parent context, since the child may rely on the functionality of the parent still. If you close the parent first as shown above, the child context may still rely on it for all sorts of purposes and therefore fail during its own shutdown procedure.