【问题标题】:How to get annotations from parent method?如何从父方法获取注释?
【发布时间】:2017-12-12 09:35:17
【问题描述】:

我有一个界面:

public interface JustToCheckInterface {

    @MyCheck(feature = "occurrence-logging")
    void log();

    void log2();

    @MyCheck(feature = "check-logging")
    void log3();
}

和实施:

@Component
public class JustToCheck implements JustToCheckInterface {

    public void log() {
        System.out.println("hello");
    }

    @MyCheck(feature = "check-no-logging")
    public void log2() {
        System.out.println("hello2");
    }

    public void log3() {
        System.out.println("hello3");
    }
}

我已经创建了注解(这个在我的界面和spring组件中使用):

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD})
@Documented
public @interface MyCheck {

    @Required
    String feature();
}

和顾问:

@Component
public class MyAdvisor extends AbstractPointcutAdvisor {
    @Autowired
    private MyMethodInterceptor myMethodInterceptor;
    private final StaticMethodMatcherPointcut pointcut = new
            StaticMethodMatcherPointcut() {
                @Override
                public boolean matches(Method method, Class<?> targetClass) {
                    return method.isAnnotationPresent(MyCheck.class);
                }
            };

    @Override
    public Pointcut getPointcut() {
        return pointcut;
    }

    @Override
    public Advice getAdvice() {
        return myMethodInterceptor;
    }
}

方法拦截器

@Component
public class MyMethodInterceptor implements MethodInterceptor {

    @Override
    public Object invoke(MethodInvocation methodInvocation) throws Throwable {
        MyCheck annotation = methodInvocation.getMethod().getAnnotation(MyCheck.class);
        if (mySpecialCheck(annotation.feature())) {
            return methodInvocation.proceed();
        }
        return null;
    }
}

它似乎几乎可以工作。如果被调用的方法(覆盖父接口)具有相应的注释,则它适用于对象。但如果接口方法具有注释,则它不适用于覆盖没有注释的接口的方法。请参阅方法log()log3()

就我而言,解决方案有两个潜在的候选者:

  • 反射解决方案(从 super 获取 superMethods 和注解);
  • 拦截器解决方案(改进一个)。

不幸的是,我在这两个方面都不强。

【问题讨论】:

    标签: java spring reflection annotations aop


    【解决方案1】:

    你可以遍历所有的超类和接口的超方法找到注解。但是您可能会发现不止一个注解,因为该方法可能在多个类或接口中声明。

    这是我的示例代码:

    public class Q46553516 {
      public static void main(String[] args) throws Exception {
        // the input method
        Method method = ClassB.class.getMethod("func");
        // get the annotation value
        Class<?> clz = method.getDeclaringClass();
        List<Anno> collect = Stream.concat(
            Stream.of(clz),
            Stream.concat(
                Stream.of(ReflectUtil.getAllSuperClasses(clz)),
                Stream.of(ReflectUtil.getAllInterfaces(clz))))
            .map(c -> {
              try {
                return c.getMethod(method.getName(), method.getParameterTypes());
              } catch (Exception e) {
                return null;
              }
            })
            .filter(m -> m != null)
            .map(m -> m.getAnnotation(Anno.class))
            .filter(a -> a != null)
            .collect(Collectors.toList());
        collect.forEach(System.out::println);
      }
    
      @Retention(RetentionPolicy.RUNTIME)
      @Target(ElementType.METHOD)
      @Documented
      @Inherited
      public @interface Anno {
        String value();
      }
    
      static interface Inter {
        @Anno("Inter")
        void func();
      }
    
      static class ClassA implements Inter {
        @Override
        @Anno("ClassA")
        public void func() {
    
        }
      }
    
      static class ClassB extends ClassA {
        @Override
        public void func() {
    
        }
      }
    }
    

    和输出:

    @xdean.stackoverflow.java.reflection.Q46553516$MyCheck(feature=ClassA)
    @xdean.stackoverflow.java.reflection.Q46553516$MyCheck(feature=Inter)
    

    我使用了我的实用程序ReflectUtil,你可以找到它here

    【讨论】:

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