Java CDI。拦截器仅在 class 中的第一个方法调用中被调用
Java CDI. Interceptor is only invoked in the first method call in a class
我正在使用 CDI 拦截器,我意识到只有 class 中用 @Interceptor 注释的第一个方法调用被拦截。在下面的示例中,方法 B 永远不会被拦截。
@InterceptorBinding
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Transactional {
}
@Transactional
@Interceptor
public class TransactionsInterceptor {
@AroundInvoke
public Object transactionInterceptor(InvocationContext context) throws Exception {
System.out.println("Method="+context.getMethod().getName());
return context.proceed();
}
}
public Interface AnImportantInterface {
public void methodA();
public void methodB();
}
@Transactional
@ThreadScoped
public class AnImportantClass implements AnImportantInterface {
public void methodA() {
methodB();
}
public void methodB() {
//This method is never intercepted
}
}
public class AnotherImportantClass {
@Inject AnImportantInterface aui;
public void someMethod() {
aui.methodA();
}
}
如果先调用methodA,如何实现methodB被拦截?有什么解决方法吗?
这是因为您是直接调用 methodB()
而不是通过 CDI 代理,因此永远不会调用拦截器。只有在使用其代理调用 CDI bean 方法时才会调用拦截器。您应该将方法 B 移动到另一个 CDI bean 中,并将其 @Inject
移动到这个 bean 中,然后从 methodA
将 methodB()
更改为 bean2.methodB(..)
.
使用自我注入。 Bean 自注入可以很容易地在 CDI 中实现——只需注入一个实例,其中 T 是实现。
@Named
public class Foo implements Fooable{
@Inject
private Instance<Foo> foo;
public void executeFirst(){
foo.get().executeSecond();
}
@Transactional
public void executeSecond(){
//do something
}
}
这样,您就可以在同一个 bean 中执行您的方法。如果 bean 是有状态的,请确保 select 正确的范围。还要确保实例的通用类型 T 直接是实现 - 这确保每次都实现正确的对象。
我正在使用 CDI 拦截器,我意识到只有 class 中用 @Interceptor 注释的第一个方法调用被拦截。在下面的示例中,方法 B 永远不会被拦截。
@InterceptorBinding
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Transactional {
}
@Transactional
@Interceptor
public class TransactionsInterceptor {
@AroundInvoke
public Object transactionInterceptor(InvocationContext context) throws Exception {
System.out.println("Method="+context.getMethod().getName());
return context.proceed();
}
}
public Interface AnImportantInterface {
public void methodA();
public void methodB();
}
@Transactional
@ThreadScoped
public class AnImportantClass implements AnImportantInterface {
public void methodA() {
methodB();
}
public void methodB() {
//This method is never intercepted
}
}
public class AnotherImportantClass {
@Inject AnImportantInterface aui;
public void someMethod() {
aui.methodA();
}
}
如果先调用methodA,如何实现methodB被拦截?有什么解决方法吗?
这是因为您是直接调用 methodB()
而不是通过 CDI 代理,因此永远不会调用拦截器。只有在使用其代理调用 CDI bean 方法时才会调用拦截器。您应该将方法 B 移动到另一个 CDI bean 中,并将其 @Inject
移动到这个 bean 中,然后从 methodA
将 methodB()
更改为 bean2.methodB(..)
.
使用自我注入。 Bean 自注入可以很容易地在 CDI 中实现——只需注入一个实例,其中 T 是实现。
@Named
public class Foo implements Fooable{
@Inject
private Instance<Foo> foo;
public void executeFirst(){
foo.get().executeSecond();
}
@Transactional
public void executeSecond(){
//do something
}
}
这样,您就可以在同一个 bean 中执行您的方法。如果 bean 是有状态的,请确保 select 正确的范围。还要确保实例的通用类型 T 直接是实现 - 这确保每次都实现正确的对象。