3

目前,我们在 JavaEE 6 上的 @PostConstruct 方法中遇到了一个更复杂的初始化问题。有几个地方可能会出错并且会出现异常。在那种情况下,我们可能有一个半初始化的 bean。

在这种情况下会调用@PreDestroy 方法吗?我们可以在那里检查我们的资源并在必要时释放它们。还是我们需要在@PostConstruct 中捕获所有异常并清理那里的所有内容?规范对此并不清楚(或者我可能没有找到)。

或者,由于缺乏规范,它是特定于供应商的吗?JBoss 7.x 上的情况如何?

4

1 回答 1

3

我认为 EJB3.1 规范在这种情况下很明确:如果您在 PostConstruct 中获取了非托管资源,那么您必须自己释放它们以防异常。

第 14.3.3 节 - 来自会话 Bean 容器操作的 PostConstruct 和 PreDestroy 方法的异常:记录异常或错误。如果是 Singleton,则回滚任何容器启动的事务。丢弃实例。

第 14.3.11 节 - 资源释放 当容器因为系统异常而丢弃一个实例时,容器应该释放该实例持有的所有资源,这些资源是通过在企业 bean 环境中声明的资源工厂获取的(参见第 16.7 小节)。

注意:虽然容器应该释放实例通过企业 bean 环境中声明的资源工厂获取的资源管理器的连接,但容器通常不能释放实例可能通过 JDK API 获取的“非托管”资源. 例如,如果实例打开了 TCP/IP 连接,大多数容器实现将无法释放连接。该连接最终会被 JVM 垃圾收集器机制释放。

以下 2 节指定当在 EJB 业务方法或 @PostContruct 内部发生 RuntimeException 时不调用 @PreDestroy 方法:

4.7.3 异常处理 RuntimeException 不是企业 bean 类的任何方法(包括业务方法和容器调用的生命周期回调拦截器方法)抛出的应用程序异常,导致转换到“不存在”状态. 异常处理在第 14 章中有详细描述。当多个此类方法应用于 bean 类时,有关生命周期回调拦截器方法的规则,请参见第 12.5.1 节。从客户端的角度来看,会话对象继续存在。客户端可以继续访问会话对象,因为容器可以将客户端的请求委托给另一个实例。

12.5.1Exceptions 生命周期回调拦截器方法可能会抛出系统运行时异常,但不会抛出应用程序异常。任何生命周期拦截器回调方法抛出的运行时异常都会导致 bean 实例及其拦截器在拦截器链展开后被丢弃 [59]。当 bean 和拦截器因此类异常而被丢弃时,不会调用 PreDestroy 回调:链中的生命周期回调拦截器方法应在拦截器链展开时执行任何必要的清理操作。

于 2013-01-30T09:10:06.183 回答