Interceptor

概念: 開始・終了処理に割り込み、業務と直接関連ないシステム処理を実行

例:

・Logging

・セキュリティ関連(認証・認可)

・トランザクション(Commit・Rollback)

Interceptor Demo

※他サイトを参照

★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() { }

}