在JavaEE 6中@PostConstruct中的异常后调用了@PreDestroy吗?

时间:2013-01-30 08:18:10

标签: java-ee jboss ejb java-ee-6 cdi

目前,我们在JavaEE 6上的@PostConstruct方法中存在更复杂的初始化问题。有几个地方可能出现问题以及预期会出现异常。在这种情况下,我们可能有一半初始化的bean。

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

或者,由于缺乏规范,它是供应商特定的吗?怎么在JBoss 7.x上?

1 个答案:

答案 0 :(得分:3)

我认为在这种情况下EJB3.1规范是明确的:如果你在PostConstruct中获得了非托管资源,那么你必须自己发布它们以防万一。

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

第14.3.11节 - 资源的发布 当容器因系统异常而丢弃实例时,容器应释放通过企业bean环境中声明的资源工厂获取的实例所拥有的所有资源(参见第16.7节)。

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

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

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

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