首页 > 解决方案 > 如何将存储在 mongodb 中的 getter 方法用于其他 POJO 类?

问题描述

我有一个类具有 getter 和 setter 方法,我将该 getter 方法与其他一些集合一起存储在 mongodb 中。从数据库获取方法名称后如何访问该方法。是否可以这样做?

public class MappingAlgorithmScoreGenerationRules {

    @Field(value = FieldNames.CATEGORY)
    private String category;

    @Field(value = FieldNames.ATTRIBUTE_NAME)
    private MappingScoreGenerationLogic attributeName;

    @Field(value = FieldNames.PRIORITY)
    private Integer priority;

    @Field(value = FieldNames.ATTRIBUTE_SCORE)
    private Integer attributeScore;

    @Field(value = FieldNames.FINAL_THRESHOLD)
    private Integer finalThreshold;

    @Field(value = FieldNames.RESULT_COUNT)
    private Integer resultCount;

    @Field(value = FieldNames.NORMALIZED_VALUE)
    private Integer normalizedValue;

    @Field(value = FieldNames.GETTER_METHOD)
    private String getterMethod;
}

这是我存储方法名称的类。

public class MatchEntry {

    private double matchedWeight;

    public double getMatchedWeight() {
        return matchedWeight;
    }

    public void setMatchedWeight(double matchedWeight) {
        this.matchedWeight = matchedWeight;
    }
}

getMatchedWeight 是我要存储在 DB MappingAlgorithmScoreGenerationRules 中的方法名称。

获取方法名后如何访问方法名?我想访问例如:MatchEntry.(the value get from db)

标签: javamongodb

解决方案


在 Java 中,您可以使用反射 ( https://docs.oracle.com/javase/tutorial/reflect/member/methodInvocation.html )按名称实现方法访问。这是一个教程,您可以使用它来更多地了解此语言功能:https ://www.geeksforgeeks.org/reflection-in-java/

在您的示例中,假设您已经MappingAlgorithmScoreGenerationRules从数据库加载了一个实例,其getterMethod属性返回“getMatchedWeight”。我们还假设您有一个MatchEntry.

然后,您将访问如下:

MappingAlgorithmScoreGenerationRules rules = ....; //load from DB
MatchEntry entry = ...; //wherever it comes from

String getterMethodName = rules.getGetterMethod();

Method getter = MatchEntry.class.getMethod(getterMethodName);
Object value = getter.invoke(entry);

此代码片段省略了异常,特别是NoSuchMethodExceptionInvocationTargetException.


请注意,如果您选择这种方法,并且很大程度上取决于您的域模型的其余部分,您还需要非常小心对实际值的返回类型的假设(除非您可以以某种方式保证它们都是相同的,在这种情况下,您可以转换该值)。

使用反射的代码本身也很脆弱,一旦重构就容易失败。想象一下,您有一个包含这些规则的填充数据库,并且在代码审查期间,一些方法被重命名。无意义的变化?或者您的整个设置会在下一次部署时中断?

一种(类型)更安全的方法可能是确保所有条目和相关对象都从标准化getValue(String attributeName)方法返回类型的接口派生,因此您可以这样做而不是弄乱反射:

MappingAlgorithmScoreGenerationRules rules = ....; //load from DB
MatchEntry entry = ...; //wherever it comes from

String attributeName = rules.getAttribute(); //instead of 'getterMethod'

Object value = entry.getValue(attributeName);

其中 MatchEntry.getValue 可能定义为:

public Object getValue(String attribute) {
    switch(attribute) {
        case "matchedWeight": return getMatchedWeight();
        default: return null; //or you could throw an exception
    }
}

这将很容易在任何类型的方法名称重构和重组中幸存下来,但会增加为每个新属性添加 case 到 switch 的开销。

这个问题可以通过运行时注释部分解决,该注释本质上将属性名称绑定到 getter 方法,例如:

public class MatchEntry implements Matchable {

    private double matchedWeight;

    @MyCustomAnnotation("matchedWeight")
    public double getMatchedWeight() {
        return matchedWeight;
    }

    public void setMatchedWeight(double matchedWeight) {
        this.matchedWeight = matchedWeight;
    }
}

public interface Matchable {
    default Object getValue(String attributeName) {
        //read methods annotated with 'MyCustomAnnotation's in current class and call the one with matching value
    }
}

您的getValue(String attributeName)任务是阅读这些注释并动态确定要调用的 getter。仍然需要在需要的任何地方添加注释,但至少它与 getter 一起使用,而不是隐藏在可能跨多个类定义重复的某个开关中。相反,您只需要在父界面中有一个默认定义,如上所示。


推荐阅读