Interceptor
概念: 開始・終了処理に割り込み、業務と直接関連ないシステム処理を実行
例:
・Logging
・セキュリティ関連(認証・認可)
・トランザクション(Commit・Rollback)
※他サイトを参照
★Interceptorの種類
AroundInvokeインターセプタ
import java.util.logging.Logger;
import javax.interceptor.AroundInvoke;
import javax.interceptor.InvocationContext;
@Stateless
public class MyEJB {
private Logger logger = Logger.getLogger(this.getClass().toString());
@AroundInvoke
private Object log(InvocationContext ic) throws Exception {
logger.entering(ic.getTarget().toString(), ic.getMethod().getName());
try {
return ic.proceed();
} finally {
logger.exiting(ic.getTarget().toString(), ic.getMethod().getName());
}
}
...
}
メソッド・インターセプタ
public class LoggingInterceptor {
...
@AroundInvoke
private Object log(InvocationContext ic) throws Exception {
...
}
}
import javax.interceptor.Interceptors;
@Stateless
//@Interceptors(LoggingInterceptor.class)
public class MyEJB {
@Interceptors(LoggingInterceptor.class)
public void createBook(Book book) {
...
}
}
ライフサイクル・コールバック・インターセプタ
public class LoggingInterceptor {
...
@PostConstruct
private Object log(InvocationContext ic) throws Exception {
...
}
@PreDestroy
private Object log(InvocationContext ic) throws Exception {
long startTime = System.currentTimeMillis();
try {
return ic.proceed();
} finally {
long endTime = System.currentTimeMillis();
logger.fine(ic.getMethod() + ":" + (endTime - startTime));
}
}
}
@Stateless
@Interceptors(LoggingInterceptor.class)
public class MyEJB {
@PostConstruct
public void init() {
...
}
...
}
★インターセプタの連続と除外
import javax.interceptor.Interceptors;
import javax.interceptor.ExcludeDefaultInterceptors;
import javax.interceptor.ExcludeClassInterceptors;
@Stateless
@ExcludeDefaultInterceptors
@Interceptors(A.class, B.class)
public class MyEJB {
@Interceptors(C.class, D.class)
public void methodA() {
...
}
@ExcludeClassInterceptors
public void methodB() {
...
}
}
A⇒B⇒C⇒Dの順
デフォルト・インターセプタの設定
ejb-jar.xml
<assembly-descriptor>
<interceptor-binding>
<ejb-name>*</ejb-name>
<interceptor-class>
com.test.LoggingInterceptor
</interceptor-class>
</interceptor-binding>
</assembly-descriptor>
クライアント
↓↑
デフォルト・インターセプタ
↓↑
クラス・インターセプタ
↓↑
メソッド・インターセプタ
↓↑
セッションBean
★サンプル
●Logging
@InterceptorBinding
@Retention(RUNTIME)
@Target({METHOD, TYPE})
public @interface LoggingInterceptorBinding{ }
@LoggingInterceptorBinding
public class MyBean {
...
}
@Interceptor
@LoggingInterceptorBinding
public class LogInterceptor {
@AroundInvoke
public Object log(InvocationContext context) {
context.getMethod().getName();
context.getParameters();
return context.proceed();
}
}
●Transaction
@InterceptorBinding
@Retention(RUNTIME)
@Target({METHOD, TYPE})
public @interface Transactional{ }
@Transactional
public class MyBean {
...
@Transactional
public void checkOut() {
...
}
}
@Interceptor
@Transactional
public class TransactionInterceptor {
@Resoucre
private UserTransaction tx;
@AroundInvoke
public Object doTransaction(InvocationContext context) {
tx.begin();
Object response = context.proceed();
tx.commit();
return response;
}
}
★優先順位
方法1
WEB-INF/beans.xml (JavaEE 7から必要がなくなった)
<interceptors>
<class>com.xxx.MyInterceptor1</class>
<class>com.xxx.MyInterceptor2</class>
</interceptors>
方法2(Java EE7)
@TimeLog
@Interceptor
@Priority(Application+10) // @Priority(Interceptor.Priority.LIBRARY_BEFORE)
public class MyInterceptor1 { ... }
@DateLog
@Interceptor
@Priority(Application+20) // @Priority(Interceptor.Priority.APPLICATION)
public class MyInterceptor2 { ... }
PLATFORM_BEFORE 0
LIBRARY_BEFORE 1000
APPLICATION 2000
LIBRARY_AFTER 3000
PLATFORM_AFTER 4000
★Interceptorの継承
@InterceptorBinding
@Target({TYPE, METHOD})
@Retention(RUNTIME)
public @interface Log {
}
@InterceptorBinding
@Target({TYPE, METHOD})
@Retention(RUNTIME)
public @interface Time {
}
@Inherited
@InterceptorBinding
@Target({TYPE, METHOD})
@Retention(RUNTIME)
@Log
@Time
public @interface TimeAndLog {
}
@Interceptor
@Log
public class LogInterceptor implements Serializable { }
@Interceptor
@Time
public class TimeInterceptor implements Serializable { }
利用例
@Interceptors(LogInterceptor.class)
@Stateful
public class MyEJBBean implements Serializable { }
@Log
@Stateful
public class MyEJBBean implements Serializable {
@Time
public Integer getPrice() { }
}
@Stateful
public class MyEJBBean implements Serializable {
@TimeAndLog
public Integer getPrice() { }
}