创建仅适用于特定返回类型[AOP]的自定义方法级别注释 [英] Create custom method level annotation only available to specific return types [AOP]

查看:226
本文介绍了创建仅适用于特定返回类型[AOP]的自定义方法级别注释的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想创建一个注释,该注释仅适用于特定类型的返回值.

I want to create an annotation which is only available to a specific type of return values.

例如,这是我的注释.

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

}

我还有一个界面:

public interface MyInterface {
    String generateKey();
}

实现我的界面的示例类:

An example class that implements my interface:

public class ExampleClass implements MyInterface {

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

因此,在这些之后,如果返回类型未实现MyInterface,我想以甚至不编译的方式配置注释.

So after these, I want to configure my annotation in a way that it won't even compile if the return type is not implementing MyInterface.

在这种情况下,我希望它可以编译良好:

In this case, I expect this to compile fine:

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

这不能编译:

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

我想知道这是否有可能.当然,我可以检查参数是否在我的Aspect类中实现了此接口,但最好在我的库中按顺序进行这种保护以防止滥用任何注释.

I wonder if this is possible in any way. Sure I can check if the parameters implements this interface in my Aspect class but it would be better to have this kind of protection in my library in order to prevent misuse of any annotation.

推荐答案

Helper classer:

这些直接来自您的示例,其中包含程序包名称和导入.

These are directly from your example, just with package names and imports.

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或其任何实现类.目的是使编译失败.

This class has some annotated and some non-annotated methods. One annotated method does not return MyInterface or any of its implementing classes. The goal is to fail compilation.

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或任何子类型或实现类.
  • all method executions
  • where the method has @MyAnnotation
  • but where the return type is different from MyInterface or any subtype or implementing class.

这是在Eclipse中的结果:

This is what the result looks like in Eclipse:

当然,如果从命令行或通过AspectJ Maven插件或类似工具进行编译,则编译错误是相同的.

Of course the compilation error is just the same if you compile from command line or via AspectJ Maven plugin or similar.

如果您不喜欢本机语法(我更喜欢它,但出于某些不可理解的原因,其他人似乎更喜欢@AspectJ样式):

If you do not like native syntax (I prefer it but for some incomprehensible reason other people seem to prefer @AspectJ style):

常规检查方面(基于注释的@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";
}

另请参阅我的相关答案:

See also my related answers here:

  • https://stackoverflow.com/a/27121947/1082681
  • https://stackoverflow.com/a/54067850/1082681
  • https://stackoverflow.com/a/41700647/1082681
  • https://stackoverflow.com/a/27312472/1082681
  • https://stackoverflow.com/a/50126576/1082681

这篇关于创建仅适用于特定返回类型[AOP]的自定义方法级别注释的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆