Suz*_*ioc 16 java spring multithreading
在Spring javadoc中说,"请注意,Lifecycle接口仅支持顶级单例bean." 这里的URL
我的LifecycleBeanTest.xml描述bean如下:
<beans ...>
<bean id="lifecycle" class="tests.LifecycleBean"/>
</beans>
Run Code Online (Sandbox Code Playgroud)
所以它看起来很"热"和"单调".
这是什么意思?如何让Spring知道我的bean实现Lifecycle并用它做点什么?
假设我的main方法在Spring中看起来如下
public static void main(String[] args) {
new ClassPathXmlApplicationContext("/tests/LifecycleBeanTest.xml").close();
}
Run Code Online (Sandbox Code Playgroud)
所以,它实例化上下文然后立即关闭它.
我可以在我的配置中创建一些bean,这会延迟close()执行直到应用程序执行所有操作吗?那么主方法线程等待应用程序终止?
例如,以下bean不按我想象的方式工作.也start()没有stop()被称为.
package tests;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.Lifecycle;
public class LifecycleBean implements Lifecycle {
private static final Logger log = LoggerFactory.getLogger(LifecycleBean.class);
private final Thread thread = new Thread("Lifecycle") {
{
setDaemon(false);
setUncaughtExceptionHandler(new UncaughtExceptionHandler() {
@Override
public void uncaughtException(Thread t, Throwable e) {
log.error("Abnormal thread termination", e);
}
});
}
public void run() {
for(int i=0; i<10 && !isInterrupted(); ++i) {
log.info("Hearbeat {}", i);
try {
sleep(1000);
} catch (InterruptedException e) {
return;
}
}
};
};
@Override
public void start() {
log.info("Starting bean");
thread.start();
}
@Override
public void stop() {
log.info("Stopping bean");
thread.interrupt();
try {
thread.join();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return;
}
}
@Override
public boolean isRunning() {
return thread.isAlive();
}
}
Run Code Online (Sandbox Code Playgroud)
更新1
我知道我可以在代码中等待bean.挂钩Spring本身很有意思.
我从未使用过Lifecycle界面,我不确定它是如何工作的。但看起来只需调用start()上下文即可调用这些回调:
AbstractApplicationContext ctx = new ClassPathXmlApplicationContext("...");
ctx.start();
Run Code Online (Sandbox Code Playgroud)
但通常我使用@PostConstruct/@PreDestroy注释或实现InitializingBean或DisposableBean:
public class LifecycleBean implements InitializingBean, DisposableBean {
@Override
public void afterPropertiesSet() {
//...
}
@Override
public void destroy() {
//...
}
}
Run Code Online (Sandbox Code Playgroud)
请注意,我没有调用close()应用程序上下文。LifecycleBean由于您在JVM中创建非守护线程,即使main退出,该线程仍保持运行。
当您停止该线程时,JVM 存在,但没有正确关闭应用程序上下文。基本上最后一个非守护线程停止,导致整个 JVM 终止。这是一个有点 hacky 的解决方法 - 当您的后台非守护线程即将完成时,显式关闭应用程序上下文:
public class LifecycleBean implements ApplicationContextAware /* ... */ {
private AbstractApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext applicationContext) {
this.applicationContext = (AbstractApplicationContext)applicationContext;
}
public void run() {
for(int i=0; i<10 && !isInterrupted(); ++i) {
log.info("Hearbeat {}", i);
try {
sleep(1000);
} catch (InterruptedException e) {
}
}
applicationContext.close();
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
14461 次 |
| 最近记录: |