1

我一直在玩注释,我想知道如何去做。我想做的是能够在类中声明一个字段并进行注释,以便该字段将使用该类的静态实例进行初始化。

给定这样的注释:

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME) //or would this be RetentionPolicy.CLASS?
public @interface SetThisField {
}

像这样的东西:

public class Foo {

    @SetThisField
    private Bar bar;
}

我已经尝试过使用解析器并在运行时设置它,它可以工作,但并不像我想要的那样优雅。

我找不到任何真正好的 RetentionPolicy.CLASS 示例,但文档似乎表明我可以以某种方式将“bar”的声明编译成这样:

private Bar bar = Bar.getInstance();

当然,它在源代码中不会这样,但在字节码中会这样,并且在运行时会表现得像那样。

那我是不是在这儿?这可能吗?还是解析器可以使用它?

更新:这是我正在使用的解析器的胆量

public static void parse(Object instance) throws Exception {

    Field[] fields = instance.getClass().getDeclaredFields();

    for (Field field : fields) {
        //"Property" annotated fields get set to an application.properties value
        //using the value of the annotation as the key into the properties
        if (field.isAnnotationPresent(Property.class)) {
            Property property = field.getAnnotation(Property.class);

            String value = property.value();

            if (!"".equals(value)) {
                setFieldValue(instance, field, properties.getProperty(value));
            }
        }

        //"Resource" annotated fields get static instances of the class allocated
        //based upon the type of the field.
        if (field.isAnnotationPresent(Resource.class)) {
            String name = field.getType().getName();
            setFieldValue(instance,  field, MyApplication.getResources().get(name));
        }
    }
}

private static void setFieldValue(Object instance, Field field, Object value) throws IllegalAccessException {
    boolean accessibleState = field.isAccessible();
    field.setAccessible(true);
    field.set(instance, value);
    field.setAccessible(accessibleState);
}
4

1 回答 1

2

我建议在运行时进行替换。这更容易实现和测试。在构建时更改字节码相对容易出错并且很难正确处理。例如,您需要了解字节码的结构以及在这种情况下如何将代码添加到代码中正确位置的所有构造函数。

如果将保留设置为 RUNTIME,则可以有一个库来检查注释并在创建对象后设置值。

于 2013-05-31T21:21:13.813 回答