Java自定义注释来查找方法

时间:2015-05-25 17:31:39

标签: java annotations

我想创建一个注释(我可以为其设置某种id),我可以将其放在变量上,而write方法通过注释setted id返回此变量的getter或setter方法;

作为示例我做了类似的事情,但仅用于方法,所以我需要两个注释用于setter和getter方法,或者向一个注释添加更多参数。也许有可能为变量创建一个注释,然后找到我需要的方法(setter或getter)?

我设法做的事情:

注释类:

    public @interface FieldRawValue {

    String value() default "";
}

带有getter和setter的模型类(带有getters的注释):

公共类PajamuModel扩展了AbstractModel {

private String id;
private String pajamuType;
private String pajamuSource;
private Date pajamuData;
private double pajamuSuma;
private String valiuta;
private String note;

@FieldRawValue(value = "pajamuType")
public String getPajamuType() {
    return pajamuType;
}

public void setPajamuType(String pajamuType) {
    this.pajamuType = pajamuType;
}

@FieldRawValue(value = "pajamuSource")
public String getPajamuSource() {
    return pajamuSource;
}

public void setPajamuSource(String pajamuSource) {
    this.pajamuSource = pajamuSource;
}

@FieldRawValue(value = "pajamuData")
public Date getPajamuData() {
    return pajamuData;
}...

通过注释值返回数据的方法:

public class AbstractModel {

public Object get(String fieldName) {
    Class<? extends AbstractModel> obj = this.getClass();

    for (Method method : obj.getDeclaredMethods()) {
        if (method.isAnnotationPresent(FieldRawValue.class)) {
            FieldRawValue annotation = method
                    .getAnnotation(FieldRawValue.class);
            if (annotation.value().equals(fieldName)) {
                try {
                    return method.invoke(obj);
                } catch (IllegalAccessException | IllegalArgumentException
                        | InvocationTargetException e) {
                    e.printStackTrace();
                    return null;
                }
            }
        }
    }

    return null;
}

顺便说一句,没有经过测试的get(String fieldName)方法,但我希望它有效。

那么可以在变量上设置注释,然后在需要时找到set或get方法吗?

1 个答案:

答案 0 :(得分:2)

我不确定您为什么要复制fieldname并将其放在注释中,但是这里是解决方案(需要Java8):

public class AbstractModel {

    public Object get(String fieldName) throws InvocationTargetException, IllegalAccessException {
        FieldRawValue fieldRawValueAnnotation = validateExistsAndGetFieldRawValueAnnotation(fieldName);

        String fieldRawValueString = fieldRawValueAnnotation.value();

        Optional<Method> getterMethodOptional = Stream.of(getClass().getMethods())
                .filter(method1 -> method1.getName().equalsIgnoreCase("get" + fieldRawValueString))
                .findFirst();

        return getterMethodOptional
                .orElseThrow(() -> new RuntimeException("No getter found for @FieldRawValue with value: " + fieldRawValueString))
                .invoke(this);
    }

    public Object set(String fieldName, Object value) throws InvocationTargetException, IllegalAccessException {
        FieldRawValue fieldRawValueAnnotation = validateExistsAndGetFieldRawValueAnnotation(fieldName);

        String fieldRawValueString = fieldRawValueAnnotation.value();

        Optional<Method> getterMethodOptional = Stream.of(getClass().getMethods())
                .filter(method1 -> method1.getName().equalsIgnoreCase("set" + fieldRawValueString))
                .findFirst();

        return getterMethodOptional
                .orElseThrow(() -> new RuntimeException("No setter found for @FieldRawValue with value: " + fieldRawValueString))
                .invoke(this, value);
    }

    private FieldRawValue validateExistsAndGetFieldRawValueAnnotation(String fieldName) {
        Class<? extends AbstractModel> obj = this.getClass();

        FieldRawValue fieldRawValueAnnotation = null;
        try {
            fieldRawValueAnnotation = obj.getDeclaredField(fieldName).getAnnotation(FieldRawValue.class);
        } catch (NoSuchFieldException e) {
            new RuntimeException("Field not found: " + fieldName);
        }

        if(fieldRawValueAnnotation == null){
            throw new RuntimeException("FieldRawValue annotation not found for a field: " + fieldName);
        }
        return fieldRawValueAnnotation;
    }

模型+用法:

public class TestModel extends AbstractModel{

    @FieldRawValue("test2")
    private String test;

    public String getTest2() {
        return test;
    }

    public void setTest2(String test) {
        this.test = test;
    }

    public static void main(String[] args) throws InvocationTargetException, IllegalAccessException {
        TestModel testModel = new TestModel();

        Object tst = testModel.get("test"); //== null
        testModel.set("test", "newVal"); //sets new value
        testModel.get("test"); //== "newVal
    }

}