我在这里仍然有一些困扰,如果我们为六个EJBTransactionAttributeType实现分别的拦截器和绑定,并将它们打包在一个.jar文件中...我在beans.xml文件中为我的.war文件设置一些启用功能是可以的,但要求用户输入所有六个拦截器对于库开发人员来说比较麻烦...
经过几个小时我差点就认同了他的观点,但后来发现CDI有一个相当不错的解决方案。
Matt试图为每种事务传播风格创建不同的注解,例如@RequiresTransaction, @RequiresNewTransaction, @MandatoryTransaction等,而不是使用一个单一的@Transactional注解,该注解使用注解成员来指定传播风格。他担心CDI会强制他使用每个注解的单独拦截器,然后在文件中为我的.
中声明所有这些拦截器类。但有一个更好的方法::-)
首先,让我们创建一个拦截器绑定类型,该类型使用成员指定传播风格。请注意,我们不会直接在我们的Bean中使用这个。
@Inherited
@InterceptorBinding
@Target({TYPE, METHOD})
@Retention(RUNTIME)
public @interface Transactional {
@Nonbinding
TransactionPropagation value() default REQUIRED;
}
其中TransactionPropagation是一个传播风格的枚举
public enum TransactionPropagation { REQUIRED, REQUIRES_NEW, MANDATORY, ... }
CDI拦截器绑定可以被其他拦截器绑定继承。此功能允许我们将我们的@Transactional注解作为元注解使用。所以让我们将@Transactional应用到Matt的注解上,例如
@Inherited
@Transactional(REQUIRED)
@InterceptorBinding
@Target({TYPE, METHOD})
@Retention(RUNTIME)
public @interface RequiresTransaction {}
@Inherited
@Transactional(REQUIRES_NEW)
@InterceptorBinding
@Target({TYPE, METHOD})
@Retention(RUNTIME)
public @interface RequiresNewTransaction {}
我们通过注解Bean类来使用这些拦截器绑定,例如
@RequiresTransaction
public class Users {
@RequiresNewTransaction
public void login() { ... }
}
方法级别的注解应该覆盖类级别的注解。
现在我们可以使用单个拦截器类来实现事务管理
@Transactional @Interceptor
class TransactionInterceptor {
@AroundInvoke
public Object manageTransaction(InvocationContext ctx) throws Exception {
TransactionPropagation tp = getTransactionPropagation(ctx.getMethod());
...
}
/**
* Get the TransactionPropagation for the meta-annotation
*/
private TransactionPropagation getTransactionPropagation(Method m) {
//first look at method-level annotations, since they take priority
for (Annotation a: m.getAnnotations()) {
if (a.annotationType().isAnnotationPresent(Transactional.class)) {
return a.annotationType().getAnnotation(Transactional.class).value();
}
}
//now try class-level annotations
for (Annotation a: m.getDeclaringClass().getAnnotations()) {
if (a.annotationType().isAnnotationPresent(Transactional.class)) {
return a.annotationType().getAnnotation(Transactional.class).value();
}
}
return null;
}
}
这个实现所有事务传播风格的拦截器类。很酷,不是吗?