【问题标题】:How to reference methods and fields without hardcoded names?如何引用没有硬编码名称的方法和字段?
【发布时间】:2014-07-18 12:36:28
【问题描述】:

我需要在验证注册器对象中注册字段以供以后验证,它是这样的;

public class ValidationRegisterer{

    public void register(String spElPath, Validator validator){
        //puts spElPath and the related validator into a collection...
    }

}

假设我有一个 A 类;

public class A {
    private String name;

    public String getName(){
        return this.name;
    }
}

我想验证 A 对象的名称字段,然后我正在注册一个这样的验证器;

validationRegisterer.register("name", MandatoryFieldValidator.class);

validationRegisterer 已设置为使用 A 类作为根,因此它知道它应该查找 A 类以获取“名称”。为了检索值和注册验证器,我使用 Spring Expression Language (SpEl)。

但我不想在此示例中硬编码像“name”这样的字段名称,因为有人可以在不更改注册路径的情况下进行重构并更改字段名称,并且在发生运行时异常之前我们无法检测到这一点。有没有办法存储类的字段名称和方法的引用,例如 Hibernate Metadata Generated classes?

【问题讨论】:

  • 我相信你正在寻找这个:docs.oracle.com/javase/tutorial/reflect
  • private 字段是私有的是有原因的。您不应该在外部类中验证它们。最好对访问器方法进行验证——它们的名称,作为公共合同,不太可能被更改
  • 反思可以帮助你。
  • 实际上,对于 SpEl,我使用的是访问器方法,而不是直接使用字段值。当我使用“名称”作为 SpEl 表达式时,会调用 getName 方法。我不知道反射如何帮助我。我不想硬编码字段名称,并且使用反射我认为如果不硬编码字段名称就不可能知道要注册哪个验证器。

标签: java methods field


【解决方案1】:

我建议您在分配字段时自己执行验证(即在构造函数中和/或在变量的 set 方法中)。

如果您不想手动验证,请查看反射。

不要对字段名称进行硬编码,而是使用注释来标记字段以进行验证。然后,使用反射找到标记的字段。

enum ValidationType{
    NotNull,
    NotEmpty,
    NoDigits,
    NoLetters
}

@interface StringValidation {
    ValidationType validationType();
}

public class ValidationTest{
    @StringValidation(validationType = ValidationType.NotNull);
    String validateThisField;
}

在此示例中,您的反射代码需要搜索 ValidationTest 中的字段,检查 StringValidation 注释。如果存在注释,请查看 ValidationType 并执行请求的验证。

【讨论】:

  • 我认为这是一个很好的解决方案,但我需要验证的大多数类都是使用 JAXB 从 XSD 自动生成的类。我不能对此类使用注释。
【解决方案2】:

如果你有 Class 对象或类的实例,你可以像这样访问它的任何字段:

String property = "lastName";
Field field = targetObject.getClass().getDeclaredField(property);
field.setAccessible(true); //overrides private
field.set(targetObject, value);

但您也可以使用http://docs.oracle.com/javase/6/docs/api/java/lang/Class.html#getDeclaredFields() 方法获取所有字段,以接收其字段的数组。

虽然我有点想知道您是否不能只使用 Bean Validation API 并使用 Annotations 对其进行配置。

【讨论】:

  • 感谢您的回答,但我不认为反思是我想要的。我不想硬编码任何字段名称。
【解决方案3】:

您可以使用java reflection API 并调用Class#getDeclaredFields 来检索类中的所有字段,遍历此方法返回的数组并调用寄存器并将其传递给Field#getName

for(Field field : getClass().getDeclaredFields()) {
    validationRegisterer.register(field.getName(), 
        MandatoryFieldValidator.class);
}

【讨论】:

  • 感谢您的回答。一个类可以有很多字段,并且可能需要不同的验证器实现。我知道哪些字段需要哪个验证器,但我不想硬编码任何字段名称。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-05-21
  • 2023-04-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多