我有一个非常简单的 Java Weld SE 应用程序。根据文档, Weld 注册了一个应该挂钩以正确关闭容器。我希望它会尝试正确关闭所有托管 bean,但似乎容器会立即完成。
简单的 CDI bean:
@ApplicationScoped
public class CDIBean {
private static final Logger logger = Logger.getLogger(CDIBean.class.getName());
private AtomicBoolean keepRunning;
private CountDownLatch threadFinished;
public void start(@Observes ContainerInitialized event) {
logger.log(Level.INFO, "start");
}
@PostConstruct
public void postConstruct() {
logger.log(Level.INFO, "postConstruct");
keepRunning = new AtomicBoolean(true);
threadFinished = new CountDownLatch(1);
new Thread(() -> {
while (keepRunning.get()) {
try {
logger.log(Level.INFO, "Still running...");
Thread.sleep(200);
} catch (InterruptedException ie) {
throw new RuntimeException(ie);
}
}
threadFinished.countDown();;
}).start();
}
@PreDestroy
public void preDestroy() {
logger.log(Level.INFO, "preDestroy");
keepRunning.set(false);
try {
threadFinished.await();
} catch (InterruptedException ie) {
throw new RuntimeException(ie);
}
}
}
主要:
public class Main {
public static void main(String[] args) {
Weld weld = new Weld();
WeldContainer container = weld.beanClasses(CDIBean.class)
.disableDiscovery().initialize();
}
}
控制台输出(应用程序以CTRL+C
or结尾kill -15
,两者的结果相同):
INFO: WELD-000900: 3.1.3 (Final)
INFO: WELD-000101: Transactional services not available. Injection of @Inject UserTransaction not available. Transactional observers will be invoked synchronously.
INFO: WELD-ENV-002003: Weld SE container 07a30136-de8f-47f9-ad5f-fbdf85cc5b60 initialized
INFO: postConstruct
INFO: start
INFO: Still running...
INFO: Still running...
INFO: Still running...
INFO: Still running...
INFO: Still running...
INFO: Still running...
^CWeld SE container 07a30136-de8f-47f9-ad5f-fbdf85cc5b60 shut down by shutdown hook
container.close()
但是,如果使用终止程序以编程方式关闭容器,则可以正常工作:
.
.
.
INFO: Still running...
INFO: Still running...
INFO: preDestroy
INFO: WELD-ENV-002001: Weld SE container 999543ef-ae42-4617-8536-329412f3a9c7 shut down
所以我的问题是:如何让容器在SIGTERM
收到时优雅地关闭?内置的关闭钩子不会这样做......