【问题标题】:Intercept annotated classes and methods in Spring AOP or AspectJ在 Spring AOP 或 AspectJ 中拦截带注释的类和方法
【发布时间】:2019-10-20 15:58:11
【问题描述】:

所以我有一个自定义注释

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

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

我的想法是,当我直接注释方法@Intercepted 时,我将方面编织到其中——该部分有效——或者如果我注释类,则方面应该编织到它的所有(公共)方法中——即部分没有。

此外,如果我注释一个类它的一个方法,方面应该只被编织一次,方法级别的注释覆盖类级别的注释。

本质上,我想要一个“如果有类级注释,则添加类级注释,但前提是还没有方法级注释。”

我该怎么做?

【问题讨论】:

  • 我认为这不是任何注释的属性,它是注释framework。以 JAX-RS 为例,当您将过滤器注解应用于类时,该类中的所有端点也会自动通过该过滤器。
  • @GhostCat 哦。所以我将不得不寻找 AspectJ 来找到一种方法来定义我的拦截器,而不是调整我的注释实现?谢谢!
  • 我非常认为。请记住:注释就是:“附加到类或方法的注释”。注释本身不包含 any 实现。 other 代码作用于该注释的存在!
  • 我改进了你的问题标题。您所说的与“从类到方法的注释继承”无关,无论您想象的是什么。您只想拦截带注释的类和方法,无论在两者中的哪一个上找到注释。 :-)

标签: java spring-boot annotations aspectj spring-aop


【解决方案1】:

这是一个 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();
  }
}

方面:

请注意 execution(* *(..)) && 在 Spring AOP 中不是必需的,因为那里只支持方法执行连接点。切入点可能只是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())

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-12-17
    • 1970-01-01
    相关资源
    最近更新 更多