Java 在GUICE中继承AOP的注释

Java 在GUICE中继承AOP的注释,java,aop,guice,aopalliance,Java,Aop,Guice,Aopalliance,我正在使用Guice和AspectJ,我正在尝试做一些AOP来测量某些方法的执行时间 我有这个注释,它将用于注释我需要测量的所有方法: @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) @Inherited public @interface MyStopWatch { } 我有一个方法拦截器: public class MyInterceptor implements org.aopalliance.interce

我正在使用Guice和AspectJ,我正在尝试做一些AOP来测量某些方法的执行时间

我有这个注释,它将用于注释我需要测量的所有方法:

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@Inherited
public @interface MyStopWatch {
}
我有一个方法拦截器:

public class MyInterceptor implements org.aopalliance.intercept.MethodInterceptor {
  private final Logger logger = LoggerFactory.getLogger(MyInterceptor.class);

  @Override
  public Object invoke(MethodInvocation invocation) throws Throwable {
    final org.apache.commons.lang3.time.StopWatch stopWatch = org.apache.commons.lang3.time.StopWatch.createStarted();
    final Object returnedObject = invocation.proceed();
    stopWatch.stop();

    logger.info("[STOPWATCH] Method: {} - Time: {}.", invocation.getMethod().getName(), stopWatch.getTime());

    return returnedObject;
  }
}
我有这个接口

public interface MySuperClass {
  @MyStopWatch
  default void test() {
    System.out.println("Hello, world");
  }
}
然后我有一个子类继承自MySuperClass:

public class MySubClass implements MySuperClass {
}
最后,我有一个束缚:

public class MyAOPModule extends AbstractModule {
  @Override
  protected void configure() {
    bindInterceptor(
            Matchers.any(),
            Matchers.annotatedWith(MyStopWatch.class),
            new MyInterceptor()
    );
  }
}
我像这样初始化我的Guice模块:

public static void main(String[] args) throws Throwable {
  Injector injector = createInjector(new MyAOPModule());
  injector.getInstance(MySubClass.class).test(); 
}
我的问题是没有记录任何内容,就好像子类对test()方法的执行没有注释一样

有什么办法可以解决这个问题吗?

这是一个问题,不太可能很快得到解决

有几种方法可以避免这种情况,但没有一种是标准的。最有价值的来自这里:

以及
hasorinhertsannotation
类(我试图解决任何缺少的通用问题,如果任何问题仍然存在,请编辑此答案以修复它):


HasorInhertsan符号中的matches方法是否应该接收对象而不是方法?我认为需要进行检查以验证传递的对象是否是方法的实例,如果是,则强制转换它并执行流。类似于
@Override public boolean matches(Object o){if(o instanceof Method){Method Method=(Method)o;return Stream.concat(Stream.of(Method),getSuperMethods(Method)).anyMatch(this::hasARequiredAnnotation);}返回false;}
@Nacho321这基本上取决于您。但它应该是最能反映问题的东西。Guice显然足够聪明,能够做出区分,因为他们甚至有一个
Matcher.returns()
Matcher,它只匹配
Method
s,并像这个一样工作。我的猜测是,让它保持现状,让Guice发挥它的魔力。
// the configure override of a Guice Abstract Module
@Override
protected void configure() {
  bindInterceptor(any(),
      // an instance of the matcher looking for HTTP methods
      new HasOrInheritsAnnotation(GET.class, PATCH.class, PUT.class, POST.class, DELETE.class),
      // the method interceptor to bind with
      new MyInterceptor());
}
/**
 * Matcher for methods which either have, or override a method which has a given
 * annotation type from the set.
 */
public class HasOrInheritsAnnotation extends AbstractMatcher<Method> {
  private final Set<Class<? extends Annotation>> annotationTypes;

  /**
   * Construct with the types of annotations required
   * @param annotationTypes which types of annotation make this matcher match
   */
  @SafeVarArgs
  public HasOrInheritsAnnotation(Class<? extends Annotation>... annotationTypes) {
    this.annotationTypes = ImmutableSet.copyOf(annotationTypes);
  }

  @Override
  public boolean matches(Method method) {
    // join this method in a stream with the super methods to fine
    // one which has the required annotation
    return Stream.concat(
          Stream.of(method),
          getSuperMethods(method))
        .anyMatch(this::hasARequiredAnnotation);
  }

  /**
   * Do any of the annotations on the method appear in our search list?
   * @param method the method to inspect
   * @return true if any of the annotations are found
   */
  private boolean hasARequiredAnnotation(Method method) {
    return Arrays.stream(method.getDeclaredAnnotations())
        .map(Annotation::annotationType)
        .anyMatch(annotationTypes::contains);
  }

  /**
   * Provide a stream of methods from all super types of this
   * @param method the method to search with
   * @return all methods that are overridden by <code>method</code>
   */
  private Stream<Method> getSuperMethods(Method method) {
    return streamOfParentTypes(method.getDeclaringClass())
        .map(clazz -> getSuperMethod(method, clazz))
        .filter(Optional::isPresent)
        .map(Optional::get);
  }

  /**
   * A stream of every parent type in the class hierarchy
   * @param declaringClass the class to read
   * @return a stream of the immediate parent types and their parents
   */
  private static Stream<Class<?>> streamOfParentTypes(Class<?> declaringClass) {
    return Stream.of(
        // all interfaces to the declaring class
        Arrays.stream(declaringClass.getInterfaces()),

        // all the parent types of those interfaces
        Arrays.stream(declaringClass.getInterfaces())
          .flatMap(HasOrInheritsAnnotation::streamOfParentTypes),

        // the super class of the declaring class
        Optional.ofNullable(declaringClass.getSuperclass())
          .map(Stream::of)
          .orElse(Stream.empty()),

        // any parents of the super class
        Optional.ofNullable(declaringClass.getSuperclass())
          .map(HasOrInheritsAnnotation::streamOfParentTypes)
          .orElse(Stream.empty()))

        // turn from a stream of streams into a single stream of types
        .flatMap(Function.identity());
  }

  /**
   * Search for the given method in a super class. In other words, which
   * is the super class method that the given method overrides?
   * @param method the method to match
   * @param superType the type to scan
   * @return an optional with the super type's method in, or empty if not found
   */
  private static Optional<Method> getSuperMethod(Method method, Class superType) {
    try {
      return Optional.of(superType.getMethod(method.getName(), method.getParameterTypes()));
    } catch (NoSuchMethodException e) {
      // this exception means the method doesn't exist in the superclass
      return Optional.empty();
    }
  }
}