Java:如何简化复杂的注释

时间:2018-01-22 16:24:14

标签: java annotations

我们有一个非常复杂的注释结构,可以放在一个字段上。这个结构放在很多字段上,只有1个参数在改变。其余的只是复制粘贴代码。这种方法有效,但有点难看:

@Type(type = "com.company.ConstantClass", parameters = @Parameter(name = "parameterClass", value = "com.company.ChangingClass"))
ChangingClass parameter;

在上面的示例中,只有参数value会发生变化,其余的只是复制粘贴。

我想做的是创建一个"快捷方式"仅包含value参数的注释。在我们处理此问题时,参数可以从String更改为Class,以使代码不易受到重构错误的影响。

例如:

@Shortcut(value = ChangingClass.class)
ChangingClass parameter;

一个问题是@Type注释只能放在字段或方法上,所以我不能简单地创建一个带注释的注释"。

2 个答案:

答案 0 :(得分:0)

你问的是不可行的。 你可以做的是指定默认值。

public @interface Type
{
   String type() default "com.company.ConstantClass";
   Parameter parameter();
}

public @interface Parameter
{
   String name() default "parameterClass";
   String value();
}

我认为结果很干净。

@Type(parameter = @Parameter("com.company.ChangingClass"))
private ChangingClass parameter;

OR ,您必须重构提取注释值的代码以使用默认值。这样,您只能使用单个属性进行注释。

答案 1 :(得分:0)

如果第三方库使用注释,则必须加载类对象。所以我猜有一个像

这样的API
public void load(Class<?> clz);

您可以在加载课程之前定义@Shortcut并处理它。您可以使用我的实用程序类AnnotationUtil在运行时添加/删除/更改注释:

  public static void processShortcut(Field f) {
    Shortcut s = f.getAnnotation(Shortcut.class);
    if (s != null) {
      AnnotationUtil.removeAnnotation(f, Shortcut.class); // remove @Shortcut
      Parameter p = AnnotationUtil.createAnnotationFromMap(Parameter.class, ImmutableMap.of("name", "parameterClass", "value", s.value().getName())); // create @Parameter
      Type t = AnnotationUtil.createAnnotationFromMap(Type.class,
          ImmutableMap.of("type", "com.company.ConstantClass", "parameters", new Parameter[] { p })); // create @Type
      AnnotationUtil.addAnnotation(f, t); // add it on field
    }
  }

让我们测试一下我们的代码

public static class User {
  @Shortcut(User.class)
  public Object parameter;
}

public static void main(String[] args) {
  Class<?> clz = User.class;
  // process shortcut on all fields
  Arrays.stream(clz.getFields()).map(ReflectUtil::getRootField).forEach(f -> processShortcut(f));
  // submit to 3rd-party lib
  thirdParty(clz);
}

public static void thirdParty(Class<?> clz) {
  // this mock your 3rd party entry
  Arrays.stream(clz.getFields()).forEach(f -> System.out.println(f + "\t" + f.getAnnotation(Type.class)));
}

输出

public java.lang.Object xdean.stackoverflow.java.annotation.Q48386072$User.parameter    @xdean.stackoverflow.java.annotation.Q48386072$Type(type=com.company.ConstantClass, parameters=[@xdean.stackoverflow.java.annotation.Q48386072$Parameter(name=parameterClass, value=xdean.stackoverflow.java.annotation.Q48386072$User)])

您可以看到@Type确实添加到该字段。

您可以在github上找到完整的代码。