【问题标题】:Interceptor is not triggered from another EJB method in same EJB拦截器不是从同一个 EJB 中的另一个 EJB 方法触发的
【发布时间】:2023-03-22 01:54:01
【问题描述】:

场景

2x 相同的拦截器在相同的 EJB 中的 2 种方法:

...
 @Interceptors(PerformanceAuditor.class)
public Date refreshIfNecessary() {
    // there is also the PerformanceAuditor-Interceptor on this method
    Pair<Date,String> lastImportDate = importDbDAO.findLatestImportLog();

    someContainer.reloadIfNecessary(lastImportDate);
    return lastImportDate.getLeft();
}

@Interceptors(PerformanceAuditor.class)
public boolean checkAndRefreshIfNecessary(final Date importDate) {
    Date lastImportDate = refreshIfNecessary();
    return lastImportDate.after(importDate);
}
...

现在我们在外部调用这个 EJB 的方法,结果如下:

  • 调用 refreshIfNecessary() -> PerformanceAuditor 被调用 2 次​​strong>
  • 调用 checkAndRefreshIfNecessary() -> PerformanceAuditor 也被调用 2 次​​strong>! (但预计是 3 次,因为多了一层嵌套!)

那么这里发生了什么?

【问题讨论】:

    标签: java jakarta-ee ejb interceptor


    【解决方案1】:

    答案很简单:

    仅当作为“EJB 调用”(即通过其 EJB 接口)调用时,拦截器才会“触发”。但是在 checkAndRefreshIfNecessary() 中,checkAndRefreshIfNecessary() 的调用是一个简单的 Java 方法调用,因此不会被容器注意到。

    解决方案:要在内部调用 EJB 中的方法作为 EJB 调用,您必须通过其可以访问的接口,例如通过注入的 SessionContext 然后通过 context.getEJBLocalObject()...但这肯定不是一个很好的解决方案!在这种情况下,最好重新考虑您的设计!

    PS:这是一个很好的例子,人们仍然需要了解应用程序服务器的内部结构。不幸的是,从 EJB3 开始,大多数功能都非常易于使用,以至于越来越多的开发人员不会遇到内部问题,这会更频繁地导致此类错误或至少糟糕的设计......

    【讨论】:

    • 你是对的。这就是代理,例如,这种逻辑也适用于事务管理。另一个更漂亮的解决方案是让您的第一个 EJB 的责任更简单(1 个服务 = 1 个责任)。因此,如果您将第二种方法导出到另一个 EJB,您的拦截将起作用,您的应用程序将更具可读性/可维护性。
    猜你喜欢
    • 1970-01-01
    • 2014-08-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-03-10
    • 1970-01-01
    • 2017-01-19
    • 1970-01-01
    相关资源
    最近更新 更多