Google guice の AOP インターセプターバインド定義で使用される Matchers には、
OR で一致を判定するものを提供していません。
com.google.inject.matcher.Matchers の static メソッドの一覧
any() | 全て無条件に一致 |
only(Object) | 指定するObjectに限定 equals(object)で判定 |
identicalTo(Object) | 指定するObjectと一致、onlyと異なるのは、 == で判定している。 |
annotatedWith(Annotation) | 指定するアノテーションに一致 |
annotatedWith(Class<annotationType>) | 指定するアノテーションクラスに一致 |
inPackage(Package) | 指定するpackage内のクラスであることに一致 ネストは効かない |
subclassesOf(Class) | 指定するクラスのサブクラスであることに一致 ネストでも適用される |
returns(Matcher) | 指定するMatcherで検査と一致する戻り値を持つメソッドであることに一致 |
not(Matcher) | 指定するMatcherで検査して一致しない(否定)こと。 |
StackOverFlow では、こんな回答してるものがありますが、
https://stackoverflow.com/questions/53411162/how-to-match-on-type-or-method-annotation-only-once
そんな、第3引数が同じの bindInterceptor() をいくつも書くのを避けたいです。
guice でバインド定義を約束するインターフェース com.google.inject.Binder を覗いてみましょう。
void bindInterceptor( Matcher<? super Class<?>> classMatcher, Matcher<? super Method> methodMatcher, MethodInterceptor... interceptors );
です。
この第1引数クラスにマッチするもの、第2引数メソッドにマッチするものを
指定する Matchers に、OR がなくて困っているので、
Matchers 同様に
クラス条件での OR メソッド、
メソッド条件での OR メソッド
を static で用意します。
名前は、XMatchers と、なんともセンスないかもしれませんが。。。
import java.io.Serializable; import java.lang.reflect.Method; import java.util.Arrays; import java.util.stream.Collectors; import com.google.inject.matcher.AbstractMatcher; import com.google.inject.matcher.Matcher; /** * XMatchers */ public class XMatchers{ private XMatchers(){} public static Matcher<Object> or(Object...m) { return new OR(m); } private static class OR extends AbstractMatcher<Object> implements Serializable { private static final long serialVersionUID = 1L; Object[] ms; public OR(Object[] m){ ms = m; } @SuppressWarnings({ "unchecked", "rawtypes" }) @Override public boolean matches(Object t){ boolean rtn = false; for(int n=0;n < ms.length; n++){ rtn = rtn | ((Matcher)ms[n]).matches(t); } return rtn; } @Override public String toString(){ StringBuilder sb = new StringBuilder("or("); sb.append(Arrays.stream(ms).map(e->e.toString()).collect(Collectors.joining(","))); sb.append(")"); return sb.toString(); } } }
使い方のサンプル
binder().bindInterceptor( XMatchers.or( Matchers.inPackage(User.class.getPackage()), Matchers.inPackage(Item.class.getPackage()) ), XMatchers.or( Matchers.annotatedWith(Names.named("A")). Matchers.annotatedWith(Names.named("B")) ), new MyInterceptor1(), new MyInterceptor2() );