2

我想创建一个仅可用于特定类型的返回值的注释。

例如,这是我的注释。

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
public @interface MyAnnotation {

}

我也有一个界面:

public interface MyInterface {
    String generateKey();
}

实现我的接口的示例类:

public class ExampleClass implements MyInterface {

@Override
public String generateKey() {
   return "Whatever";
    }
}

所以在这些之后,我想配置我的注释,如果返回类型没有实现,它甚至不会编译MyInterface

在这种情况下,我希望它编译得很好:

@MyAnnotation
public ExampleClass anExampleMethod() {
    return new ExampleClass();
}

这不能编译:

@MyAnnotation
public String anotherMethod() {
    return "Whatever";
}

我想知道这是否可能以任何方式。当然,我可以检查参数是否在我的 Aspect 类中实现了这个接口,但最好在我的库中提供这种保护,以防止滥用任何注释。

4

1 回答 1

2

辅助分类器:

这些直接来自您的示例,仅包含包名称和导入。

package de.scrum_master.app;

import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

import java.lang.annotation.Retention;
import java.lang.annotation.Target;

@Retention(RUNTIME)
@Target(METHOD)
public @interface MyAnnotation {}
package de.scrum_master.app;

public interface MyInterface {
  String generateKey();
}
package de.scrum_master.app;

public class ExampleClass implements MyInterface {
  @Override
  public String generateKey() {
    return "Whatever";
  }
}

不应编译的类:

这个类有一些注解和一些非注解的方法。一个带注释的方法不返回或其MyInterface任何实现类。目标是使编译失败。

package de.scrum_master.app;

public class Application {
  @MyAnnotation
  public MyInterface annotatedMethodReturningInterface(int number) {
    return new ExampleClass();
  }

  @MyAnnotation
  public ExampleClass annotatedMethodReturningImplementingClass() {
    return new ExampleClass();
  }

  @MyAnnotation
  public String annotatedMethodReturningSomethingElse() {
    // This one should not compile!
    return "Whatever";
  }

  public MyInterface nonAnnotatedMethodReturningInterface(int number) {
    return new ExampleClass();
  }

  public ExampleClass nonAnnotatedMethodReturningImplementingClass() {
    return new ExampleClass();
  }

  public String nonAnnotatedMethodReturningSomethingElse() {
    return "Whatever";
  }
}

约定检查方面(本机 AspectJ 语法):

package de.scrum_master.aspect;

import de.scrum_master.app.MyAnnotation;
import de.scrum_master.app.MyInterface;

public aspect AnnotationCheckerAspect {
  declare error :
    @annotation(MyAnnotation) && execution(* *(..)) && !execution(MyInterface+ *(..)) :
    "Method annotated with @MyAnnotation must return MyInterface type";
}

这方面检查

  • 所有方法执行
  • 该方法在哪里@MyAnnotation
  • 但是返回类型不同于MyInterface任何子类型或实现类。

这是 Eclipse 中的结果:

Eclipse:编译错误

当然,如果您从命令行或通过 AspectJ Maven 插件或类似插件编译,编译错误是一样的。

如果您不喜欢本机语法(我更喜欢它,但出于某种难以理解的原因,其他人似乎更喜欢 @AspectJ 风格):

约定检查方面(基于注释的@AspectJ 语法):

package de.scrum_master.aspect;

import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.DeclareError;

@Aspect
public class AnnotationCheckerAspect {
  @DeclareError(
    "@annotation(de.scrum_master.app.MyAnnotation) && " +
    "execution(* *(..)) && " +
    "!execution(de.scrum_master.app.MyInterface+ *(..))"
  )
  static final String wrongSignatureError =
  "Method annotated with @MyAnnotation must return MyInterface type";
}

另请参阅我的相关答案:

于 2019-09-07T06:24:36.673 回答