通过注释更新字段属性

时间:2017-10-16 08:13:02

标签: java reflection annotations java-annotations

我正在审查反思如何运作或可能的工作。我有SomeClassBuilder,其中包含声明注释target : Target的属性TargetAnnotation

事情是,是否可以覆盖/更新Target的值/属性,其中在调用someMethod()时会返回注释上的参数?

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface TargetAnnotation {
    String first();
    String second();
    // other attributes
}

public class Target {
    String first;
    String second;
    // some other attributes unique only to `Target`
}

public interface TargetHelper {
    void setTarget(Target target);
}

public class SomeClassBuilder implements TargetHelper {

    @TargetAnnotation(first = "first", second = "second")
    private Target target;

    @Override public void setTarget(Target target) { this.target = target }

    public void someMethod() {
        System.out.println(target.first); // should be `first`
        System.out.println(target.second); // should be `second`
    }

}

或者甚至可以在没有TargetHelper界面的情况下进行?

让我们说TargetProcessor之前调用此SomeClassBuilder,其唯一目的是填写target : Target注释@TargetAnnotation并指定字段/属性从@TargetAnnotatonTarget

public class TargetProcessor {
    public void parse() {
        // look into `@TargetAnnotation`
        // map `@TargetAnnotation` properties to `Target`
    }
}

2 个答案:

答案 0 :(得分:0)

答案 1 :(得分:0)

这是我的代码

import static xdean.jex.util.lang.ExceptionUtil.uncheck;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.reflect.Field;
import java.util.stream.Stream;

import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import xdean.jex.util.reflect.ReflectUtil;

public class Q46765735 {

  public static void main(String[] args) {
    create(TargetDomain.class).printTarget();
  }

  public static <T> T create(Class<T> clz) {
    T target = uncheck(() -> clz.newInstance());
    Stream.of(ReflectUtil.getAllFields(clz, false)).forEach(f -> uncheck(() -> fill(target, f)));
    return target;
  }

  private static <T> void fill(T target, Field field) throws Exception {
    TargetAnnotation anno = field.getAnnotation(TargetAnnotation.class);
    if (anno == null) {
      return;
    }
    Class<?> type = field.getType();
    if (!Target.class.isAssignableFrom(type)) {
      return;
    }
    field.setAccessible(true);
    Target value = (Target) field.get(target);
    if (value == null) {
      value = (Target) type.newInstance();
    }
    value.setFirst(anno.first());
    value.setSecond(anno.second());
    field.set(target, value);
  }
}

@Retention(RetentionPolicy.RUNTIME)
@java.lang.annotation.Target({ ElementType.FIELD })
@interface TargetAnnotation {
  String first();

  String second();
}

@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
class Target {
  String first;
  String second;
}

class TargetDomain {

  @TargetAnnotation(first = "first", second = "second")
  private Target target = new Target("a", "b");

  public void printTarget() {
    System.out.println(target.first); // should be `first`
    System.out.println(target.second); // should be `second`
  }
}


提示:

  1. 您可以通过写入构造函数和getter / setter手动替换lombok。
  2. ReflectUtil.getAllFields获取该课程的所有字段。
  3. uncheck只是忽略异常,你可以使用try-catch。