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

查看:21
本文介绍了创建仅适用于特定返回类型的自定义方法级别注释 [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";
}

另见我的相关回答:

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

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