2017-10-03 15 views
1

私はインターフェイスがあります。親メソッドから注釈を取得する方法は?

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

    @Required 
    String feature(); 
} 

:私は注釈を(一方は私のインタフェースで、春の部品に使用されている)作成した

@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"); 
    } 
} 

public interface JustToCheckInterface { 

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

    void log2(); 

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

と実装アドバイザー:

@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()を参照してください。

溶液に二つの潜在的な候補がある私として:

  • 反射溶液(スーパーからsuperMethodsと注釈を取得します)。
  • インターセプター溶液(1つを改善する)。

残念ながら、私は両方とも強くありません。

答えて

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

を見つけることができます
関連する問題