私は春が大好きです。しかし、メソッド実行の前後にコードを挿入することになると、Spring/AOP が間違っていたことを認めざるを得ません。
私の謙虚な意見では、メソッド名またはメソッド名に似た正規表現をハードコーディングすることは、私たちがこれまでに経験した最後のことであるべきです。私たちは皆、2000 年代初頭の XML 地獄から苦労してそれを学びました。
対照的に、EJB3 のインターセプターはアノテーション ベースで、シンプルで読みやすく、すべてではないにしてもほとんどの問題に対処できます。Spring で EJB3 スタイルのインターセプターをコーディングできたらいいと思いませんか?
私が知っている最善の解決策は@annotation
、次のコードで行ったように、ポイントカット式で使用することです。
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface AroundExecution {
}
@Component
public class SimpleBean {
@AroundExecution
public void printGreetings(){
logger.info("Hello World 2");
}
}
@Aspect
@Component
public class SimpleAdvice {
@Around("@annotation(com.myinterceptors.springaop.AroundExecution)")
public Object adviceAround(ProceedingJoinPoint joinPoint) throws Throwable {
Object retVal = null;
try {
logger.info("Before executing");
retVal = joinPoint.proceed();
logger.info("After executing");
}
catch(Throwable e) {
logger.error("Execution error");
throw e;
}
return retVal;
}
}
注釈クラス名のハードコーディングの最後のビットを削除することは不可能のようです。
Guice を使用していた場合、次のようなことができます。
public class SimpleModule extends AbstractModule {
protected void configure() {
AroundInterceptor interceptor = new AroundInterceptor();
bindInterceptor(
Matchers.any(),
Matchers.annotatedWith(BeforeExecution.class).or(Matchers.annotatedWith(AfterExecution.class)),
interceptor
);
}
}
public class AroundInterceptor implements MethodInterceptor {
private static final Logger logger = LoggerFactory.getLogger(AroundInterceptor.class);
public Object invoke(MethodInvocation invocation) throws Throwable {
try{
if(invocation.getMethod().getAnnotation(BeforeExecution.class)!=null){
invokeBefore(invocation);
}
return invocation.proceed();
}
finally{
if(invocation.getMethod().getAnnotation(AfterExecution.class)!=null){
invokeAfter(invocation);
}
}
}
protected void invokeBefore(MethodInvocation invocation) throws Throwable {
logger.info("Intercepted before executing: "+invocation.getMethod().getName());
}
protected void invokeAfter(MethodInvocation invocation) throws Throwable {
logger.info("Intercepted after executing: "+invocation.getThis().getClass().getName()+"."+
invocation.getMethod().getName());
}
}
正確には最も美しいとは言えませんが、それは仕事を成し遂げます.
デコレータ パターンは別の方法ですが、メンテナンスに多くのオーバーヘッドが追加されます。
Spring Bean 用の JSR-299 CDI デコレーター
Spring がポイントカット式の拡張を許可して、クラス定義をパラメーターとしてサポートできるようにすると、はるかに簡単になります。@Around("@annotatedWith", MyAnnotation.class)
メタデータまたはアプリケーション コンテキストでのハード コーディングを必要としないインターセプターを Spring に実装したことがある人がいるだろうか?