在 Java EE 7 上使用 CDI 的 AOP 拦截异常记录

Intercept Exceptions for logging with CDI's AOP on Java EE 7

我有以下 class 片段,我想从中删除重复的日志记录代码并将其移动到使用 CDI 的 AOP 的拦截器。

/**
 * Javadoc omitted
 */
public abstract class JpaDao<T extends LongIdentifiable> implements
        GenericDao<T> { 

    @Override
    @Transactional
    public Long persist(T type) throws GeneralPersistenceException {
        if (type == null) {
            throw new GeneralPersistenceException("Can't persist null");
        }

        try {
            entityManager.persist(type);
            return type.getId();
        } catch (PersistenceException e) {
            String message = "Failed to persist an entity";
            logger.error(message, e);
            throw new GeneralPersistenceException(message, e);
        }

    }

    @Override
    @Transactional
    public T merge(T type) throws GeneralPersistenceException {
        if (type == null) {
            throw new GeneralPersistenceException("Can't merge null");
        }

        try {
            T mergedType = entityManager.merge(type);
            return mergedType;
        } catch (PersistenceException e) {
            String message = "Failed to merge an entity";
            logger.error(message, e);
            throw new GeneralPersistenceException(message, e);
        }
    }
}

注意下面的代码片段,它在 persistmerge 方法中重复

} catch (PersistenceException e) {
    String message = "Failed to persist an entity";
    logger.error(message, e);
    throw new GeneralPersistenceException(message, e);
}

替换上述代码段的候选代码如下:

} catch (PersistenceException e) {
    throw new GeneralPersistenceException("Failed to persist an entity", e);
}

换句话说,我希望每次抛出 GeneralPersistenceException 时,都会写入一条日志消息。我的例外情况如下:

public class GeneralPersistenceException extends Exception {
    private static final long serialVersionUID = -6057737927996676949L;

    public GeneralPersistenceException() {
    }

    public GeneralPersistenceException(String message) {
        super(message);
    }

    public GeneralPersistenceException(String message, Throwable cause) {
        super(message, cause);
    }

    public GeneralPersistenceException(Throwable cause) {
        super(cause);
    }
}

如您所见,Exception 只有构造函数。 鉴于这种情况,我有以下问题:

  1. 在 Java EE 7 兼容应用程序中解决此问题的最佳策略是将 AOP 与 CDI 结合使用吗?
  2. 如果是AOP,我应该拦截GeneralPersistenceException吗?
  3. 是否可以拦截 GeneralPersistenceException 的构造函数,或仅拦截方法(尚不存在)?
  4. 是否已经为此目的实施了一些东西,而我正在重新发明轮子?

提前致谢。

您无法拦截异常,因为它是使用 **new* 创建的,并且不会由 CDI 管理。实际上,您不应该以这种方式进行拦截。 您正在寻找的解决方案是拦截您服务中的调用,在那里捕获您的异常并将其记录下来。