我有一个spring上下文,其中我们有Runnable bean这样开始:
public void startChildAndWait(Class type) {
BaseMyDispatcher child = appContext.getBean(type);
child.initialize(this); //The child references its parent during run method
new Thread(child).start();
synchronized(LOCK_OBJECT) {
LOCK_OBJECT.wait(someTime);
}
}
BaseMyDispatcher类是一个抽象类,SampleRunnableX是带有原型范围的实现,基类基本上有@PostConstruct方法和@PreDestroy方法(其主要功能是在LOCK_OBJECT上调用notify),当然一个Run方法
我的问题是调用了PostConstruct方法,但是当Run方法完成时,对象似乎没有被销毁,因此没有调用PreDestroy方法,并且我在LOCK_OBJECT上等待父进程卡住
代码在父Runnable内部的一个函数中调用(在ThreadPoolExecutor中执行,并使用相同的方法startChildAndWait以相同的方式启动(顺序)几个子项,每次都传递一个不同的类:
startChildAndWait(SampleRunnable1.class);
if(run2IsRequired && lastExitCode == 100) {//runIsRequired are booleans
startChildAndWait(SampleRunnable2.class);
}
if(run3IsRequired && lastExitCode == 100) {//lastExitCode is an integer
startChildAndWait(SampleRunnable3.class);
}
那么如何在完成子线程时调用PreDestroy方法呢?
答案 0 :(得分:2)
与其他作用域相比,Spring不管理原型bean的完整生命周期:容器实例化,配置和组装原型对象,并将其交给客户端,没有该原型实例的进一步记录。因此,尽管无论范围如何都在所有对象上调用初始化生命周期回调方法,但在原型的情况下,不会调用已配置的销毁生命周期回调。
如果您想在run()
方法完成时发生某些事情,请将该代码放在run()
方法的末尾。
答案 1 :(得分:0)
@PreDestroy
回调方法,您需要向JVM注册一个关闭挂钩,并在JVM退出时关闭其中的应用程序上下文。
//Create applicationContext
final ApplicationContext appContext =
//register ashutdown hook on application context
Runtime.getRuntime().addShutdownHook(new Thread() {
public void run() {
appContext.close();
}});
如果你想在子线程完成时执行一些代码,最好把它放在run方法的末尾(线程本身)。
答案 2 :(得分:0)
遇到了这个问题,我使它能够在实现javax.ejb.Startup
的{{1}}上添加EJB
注释
Runnable
OR
从@Startup
@Singleton
public class Task implements Runnable{
//...
@PreDestroy
public void stop(){
stop();
}
}
上下文访问/触摸此Sigleton
对象至少一次。