2015-08-20 98 views
3

我正在使用CDI攔截器,並且我意識到只有用@Interceptor註釋的類中的第一個方法調用纔會被攔截。在下面的例子中,methodB永遠不會被攔截。Java CDI。攔截器僅在類中的第一個方法調用中調用

@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來實現該方法B被截獲?有一些解決方法嗎?

回答

4

這是因爲您直接調用methodB()而不是通過CDI代理,因此攔截器從不被調用。攔截器只有在使用其代理調用CDI bean方法時纔會被調用。您應該將方法B移入另一個CDI bean中,並將其@Inject轉換爲此格式,並從methodAmethodB()更改爲bean2.methodB(..)

+0

大部分是正確的,雖然它的值得指出的是自我注入不是在CDI規範中規定的功能。 –

+0

@JohnAment正如你所指出的那樣,在當前的CDI規範中沒有規定自我注入,儘管這不是我在回答中得到的結果,如果它受到支持(就像它在EJB規範中那樣),它將爲更清晰的解決方案提供支持。對於那些感興趣的RFE在這裏:https://issues.jboss.org/browse/CDI-414 – NBW

1

使用自我注射。 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是有狀態的,請確保選擇正確的作用域。還要確保Instance的泛型類型T是直接實現的 - 這確保了每次都實現正確的對象。