似乎最简单的方法是使用CDI拦截器来捕获异常。我们可以如下定义CDI拦截器:
@InterceptorBinding@Target({ElementType.METHOD, ElementType.TYPE})@Retention(RetentionPolicy.RUNTIME)public @interface TransactionDebugger {}定义CDI拦截器后,我们需要创建在使用拦截器注释时执行的类。我们定义一个@AroundInvoke,以便在我们注释的方法中的代码之前调用我们的代码。
invocationContext.proceed()将调用我们注释的方法,并将返回的结果(如果有的话)提供给我们。因此,我们可以
try, catch(Exception)绕过此调用以捕获任何引发的异常。然后,我们可以使用记录器(此处使用log4j)记录此异常,然后重新引发该异常,以便任何上游代码也可以获知。
重新抛出该异常还将使我们能够使用CMT(容器托管事务),因为最终容器将捕获该异常并抛出一个事务RollbackException。但是,您也可以轻松地与此同时使用UserTransactions,并在捕获异常时执行手动回滚,而不用重新抛出它。
@Interceptor@TransactionDebuggerpublic class TransactionInterceptor { private Logger logger = LogManager.getLogger(); @AroundInvoke public Object runInTransaction(InvocationContext invocationContext) throws Exception { Object result = null; try { result = invocationContext.proceed(); } catch (Exception e) { logger.error("Error encountered during Transaction.", e); throw e; } return result; }}接下来,由于在CDI中默认未启用拦截器,因此必须在bean.xml(通常位于src / meta-
INF)中包括新的拦截器。这必须在使用注释的所有项目中完成,而不仅仅是在定义注释的项目中。这是因为CDI在每个项目的基础上初始化拦截器:
<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/beans_1_1.xsd" version="1.1" bean-discovery-mode="all"> <interceptors> <class>package.database.TransactionInterceptor</class> </interceptors></beans>
最后,我们必须注释新的CDI拦截器调用的方法。在这里,我们用@Transactional注释它们以启动事务,并用@TransactionDebugger注释以捕获在事务中发生的任何异常:
@Transactional @TransactionDebuggerpublic void init() { ...}现在,这将记录执行init()代码时发生的任何错误。可以通过将Interceptor实现类TransactionInterceptor中的try捕获从Exception更改为Exception的子类来更改日志记录的粒度。



