EJB3でのAOPのためには、@AroundInvokeアノテーションを付与したメソッドを定義したインターセプタ用のクラス(これはバインドしたいクラス自身に定義してもOK)を作り、バインドしたいクラスにインターセプタクラスを@Interceptorsアノテーションを使って付与してあげればよい(クラス自身にインターセプタメソッドを定義している場合は不要)。
インターセプタメソッドの引数に取るInvocationContextでは対象のメソッドやパラメータをとってこれるので、これを使ってNullチェックを自動で挿し込めるようにしたい。
そうすると、メソッドごとに以下のようなチェックが不要になる。
if (param1 == null) { throw new IllegalArgumentException("param1 is null."); }
今回はその準備。ちょんプロでどんなインターセプタメソッドにすればよいか想像をふくらませる。
まず引数がNull以外であることを制約するためのアノテーションを作る。
import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @Retention(RetentionPolicy.RUNTIME) public @interface NotNull { }
続いて、上記の@NotNullを使ったメソッドを持つ対象のクラスを定義。Nullが許可されていない二つのIntegerを持つメソッド。
package sample; public class Sample { public int add(@NotNull Integer a, @NotNull Integer b) { return a + b; } }
NotNullチェック付きメソッドの実装。今回はメソッドの実装は、Method#invoke()をそのまま呼ぶ。
public Object invokeWithNullCheck(Object target, Method method, Object... params) throws Exception { Annotation[][] parameterAnnotations = method.getParameterAnnotations(); for (int i = 0; i < parameterAnnotations.length; i++) { Object param = params[i]; Annotation[] parameterAnnotation = parameterAnnotations[i]; for (Annotation annotation : parameterAnnotation) { if (annotation.annotationType().equals(NotNull.class)) { if (param == null) { throw new IllegalArgumentException(target.getClass().getName() + "#" + method.getName() + " contains wrong null arguments: " + Arrays.toString(params)); } } } } return method.invoke(target, params); }
で、実際に呼び出してみる(JUnitテスト)。
@Test public void testOK() throws Exception { Sample sample = new Sample(); Method method = sample.getClass().getMethod("add", Integer.class, Integer.class); assertEquals(8, ((Integer) invokeWithNullCheck(sample, method, 5, 3)).intValue()); } @Test public void testNG() throws Exception { Sample sample = new Sample(); Method method = sample.getClass().getMethod("add", Integer.class, Integer.class); try { invokeWithNullCheck(sample, method, 5, null); fail(); } catch (IllegalArgumentException e) { assertEquals( "sample.Sample#add contains wrong null arguments: [5, null]", e.getMessage()); } }