Interceptor (攔截器) 可在方法呼叫前後執行橫切邏輯:日誌、效能監控、安全檢查、交易管理等。EJB 3.0 基於註解,零配置檔即可啟用。
Hello : 遠端/本地介面HelloBean : 無狀態 Session Bean,含業務方法與類內部攔截器TracingInterceptor : 外部獨立攔截器類別Client : JNDI 查找並呼叫@Remote public interface HelloRemote extends Hello {}
@Local public interface HelloLocal extends Hello {}
public interface Hello {
void hello();
String hello2();
}
@Stateless
@Interceptors({TracingInterceptor.class}) // 類別級:外部攔截器
public class HelloBean implements HelloRemote, HelloLocal {
public void hello() { System.out.println("Hello roson"); }
public String hello2() { return "are you ok"; }
// === 方法級:Bean 內部攔截器 (針對特定方法) ===
@AroundInvoke
public Object myBeanInterceptor(InvocationContext ctx) throws Exception {
String m = ctx.getMethod().getName();
if ("hello".equals(m)) System.out.println("*** hello: ");
if ("hello2".equals(m)) System.out.println("*** hello2: ");
return ctx.proceed(); // 必須呼叫,否則業務方法不執行
}
}
public class TracingInterceptor {
@AroundInvoke
public Object log(InvocationContext ctx) throws Exception {
System.out.println("*** TracingInterceptor intercepting");
long start = System.currentTimeMillis();
try {
return ctx.proceed();
} finally {
long time = System.currentTimeMillis() - start;
String method = ctx.getTarget().getClass().getName()
+ "." + ctx.getMethod().getName() + "()";
System.out.println("*** " + method + " took " + time + "ms");
}
}
}
| 方法 | 用途 |
|---|---|
getMethod() | 取得被攔截的 java.lang.reflect.Method |
getTarget() | 取得目標 Bean 實例 (可轉型呼叫業務方法) |
getParameters() / setParameters() | 讀取/修改方法參數 |
getContextData() | 攔截器鏈間傳遞資料的 Map |
proceed() | 執行下一個攔截器或目標方法,**必須呼叫** |
public class Client {
public static void main(String[] args) throws Exception {
InitialContext ctx = new InitialContext();
Hello hello = (Hello) ctx.lookup(HelloRemote.class.getName());
hello.hello();
System.out.println(hello.hello2());
}
}
*** TracingInterceptor intercepting *** hello: Hello roson *** TracingInterceptor invocation of HelloBean.hello() took 5ms *** TracingInterceptor intercepting *** hello2: *** TracingInterceptor invocation of HelloBean.hello2() took 2ms are you ok
run.bat -c allant build → ant runlog4j.properties 避免「No appenders」警告 (文中附有範例)。
@Interceptors({FirstInterceptor.class, SecondInterceptor.class})
@Stateless
public class MyBean { ... }
執行順序:First → Second → Bean 內部 @AroundInvoke → 目標方法。
@Interceptors):通用橫切關注 (日誌、審計、安全)。@AroundInvoke):針對特定方法的精細控制 (參數驗證、快取)。