环境:Java EE 6
如何在拦截器中确定调用的 bean 是容器管理 (CMT) 还是 bean 管理 (BMT)?
根据定义,Bean 始终是容器管理的。
您可能想知道的是当前交易 CMT 还是 BMT。由于@AroundInvoke拦截器方法与被拦截的业务方法在同一事务中执行,您可以通过以下方式检查事务类型:
public class SomeInterceptor {
@Resource
private javax.ejb.SessionContext sessionContext;
@AroundInvoke
public Object intercept(InvocationContext ctx) throws Exception {
if (isCMT()) {
}
...
}
private boolean isCMT() {
try {
//throws IllegalStateException if not BMT
sessionContext.getUserTransaction();
return false;
}
catch (IllegalStateException ise) {
return true;
}
}
}
当然,使用异常来控制流是不好的,但我不知道区分 BMT 和 CMT 的替代方法。
您可以使用InvocationContext
获取Class
和Method
调用拦截器的对象。然后您可以尝试为它们解析注释并确定事务管理类型。但是这种方法有一个巨大的缺点:如果事务管理属性是使用ejb-jar.xml
部署描述符设置的,那么您根本找不到任何注释或无效的覆盖注释。您也可以尝试调用java.util.Map<java.lang.String,java.lang.Object> getContextData()
和发现结果。
似乎在错误的层面上解决了问题。如果像这样isCMT()
的测试无论如何都不是非常面向对象的。为什么不使用两个拦截器,一个用于带有 BMT 的 bean,另一个用于 CMT?为正确的 bean 使用正确的拦截器......如果需要,两个拦截器仍然可以通过继承一个公共父类来重用公共逻辑。