繁体   English   中英

在Spring AOP或AspectJ中拦截带注释的类和方法

[英]Intercept annotated classes and methods in Spring AOP or AspectJ

所以我有一个自定义注释

@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface Intercepted {}

我想用来将方面编织到方法中(AspectJ, @annotation(Intercepted) )。

这个想法是当我直接对方法@Intercepted注释时,我将方面编织起来–该部分起作用了;或者,如果我对类进行了注释,则该方面应被编织到其所有(公共)方法中—该部分不被编织。

此外,如果我注释一个类它的方法之一,该环节都要只得到穿插在一次,方法级别的注解覆盖类级别的一个。

本质上,我希望“如果存在类级注释,但仅当还没有方法级注释时,添加类级注释”。

我怎么做?

这是一个AspectJ示例。 切入点语法在Spring AOP中是相同的。

助手类:

package de.scrum_master.app;

import java.lang.annotation.*;

@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface Intercepted {}
package de.scrum_master.app;

@Intercepted
public class AnnotatedClass {
  public void doSomething() {}
  public void doSomethingElse() {}
}
package de.scrum_master.app;

public class AnnotatedMethod {
  @Intercepted
  public void doSomething() {}
  public void doSomethingElse() {}
}
package de.scrum_master.app;

@Intercepted
public class AnnotatedMixed {
  @Intercepted
  public void doSomething() {}
  public void doSomethingElse() {}
}

驱动程序应用程序(Java SE,没有Spring):

package de.scrum_master.app;

public class Application {
  public static void main(String[] args) {
    // Should be logged
    new AnnotatedClass().doSomething();
    // Should be logged
    new AnnotatedClass().doSomethingElse();

    // Should be logged
    new AnnotatedMethod().doSomething();
    // Should NOT be logged
    new AnnotatedMethod().doSomethingElse();

    // Should be logged, but only once
    new AnnotatedMixed().doSomething();
    // Should be logged
    new AnnotatedMixed().doSomethingElse();
  }
}

方面:

请注意,在Spring AOP中,无需execution(* *(..)) &&部分,因为那里仅支持方法执行连接点。 切入点可以只是annotatedMethod() || annotatedClass() annotatedMethod() || annotatedClass()在那里。 在AspectJ中,我必须更加精确,因为否则将记录其他联接点类型。

package de.scrum_master.aspect;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;

@Aspect
public class AnnotationInterceptor {
  @Pointcut("@annotation(de.scrum_master.app.Intercepted)")
  public void annotatedMethod() {}

  @Pointcut("@within(de.scrum_master.app.Intercepted)")
  public void annotatedClass() {}

  @Before("execution(* *(..)) && (annotatedMethod() || annotatedClass())")
  public void log(JoinPoint thisJoinPoint) {
    System.out.println(thisJoinPoint);
  }
}

控制台日志:

execution(void de.scrum_master.app.AnnotatedClass.doSomething())
execution(void de.scrum_master.app.AnnotatedClass.doSomethingElse())
execution(void de.scrum_master.app.AnnotatedMethod.doSomething())
execution(void de.scrum_master.app.AnnotatedMixed.doSomething())
execution(void de.scrum_master.app.AnnotatedMixed.doSomethingElse())

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM