当util类方法名称与每个类实现(而不是接口)匹配时,具有接口的util类调用方法

时间:2018-09-07 17:07:24

标签: java jaxb auto-generate

首先,我对奇怪的标题表示歉意。我真的不知道该怎么称呼。

我们有一个“ Factory”类,其中包含针对所生成的Bean中存在的每个属性的方法。 Factory类的每个方法均以与包含该属性的特定类相关的方式命名,并旨在创建该属性的JAXBElement。不幸的是,该类也是自动生成的。看起来像这样:

public class Factory {
    private final static QName _MyClassImpl1Attribute1Name_QNAME = new QName("urn:some.urn", "attribute1Name");
    private final static QName _MyClassImpl1Attribute2Name_QNAME = new QName("urn:some.urn", "attribute2Name");

    private final static QName _MyClassImpl2Attribute1Name_QNAME = new QName("urn:some.urn", "attribute1Name");
    private final static QName _MyClassImpl2Attribute2Name_QNAME = new QName("urn:some.urn", "attribute2Name");

    /**
     * Create an instance of {@link JAXBElement }{@code <}{@link String }{@code >}}
     * 
     */
    @XmlElementDecl(namespace = "urn:some.urn", name = "attribute1Name", scope = MyClassImpl1.class)
    public JAXBElement<String> createMyClassImpl1Attribute1Name(String value) {
        return new JAXBElement<String>(_MyClassImpl1Attribute1Name_QNAME, String.class, MyClassImpl1.class, value);
    }

    /**
     * Create an instance of {@link JAXBElement }{@code <}{@link Boolean}{@code >}}
     * 
     */
    @XmlElementDecl(namespace = "urn:some.urn", name = "attribute2Name", scope = MyClassImpl1.class)
    public JAXBElement<Boolean> createMyClassImpl1Attribute2Name(Boolean value) {
        return new JAXBElement<Boolean>(_MyClassImpl1Attribute2Name_QNAME, Boolean.class, MyClassImpl1.class, value);
    }

    /**
     * Create an instance of {@link JAXBElement }{@code <}{@link String }{@code >}}
     * 
     */
    @XmlElementDecl(namespace = "urn:some.urn", name = "attribute1Name", scope = MyClassImpl2.class)
    public JAXBElement<String> createMyClassImpl2Attribute1Name(String value) {
        return new JAXBElement<String>(_MyClassImpl2Attribute1Name_QNAME, String.class, MyClassImpl2.class, value);
    }

    /**
     * Create an instance of {@link JAXBElement }{@code <}{@link Boolean}{@code >}}
     * 
     */
    @XmlElementDecl(namespace = "urn:some.urn", name = "attribute2Name", scope = MyClassImpl2.class)
    public JAXBElement<Boolean> createMyClassImpl2Attribute2Name(Boolean value) {
        return new JAXBElement<Boolean>(_MyClassImpl2Attribute2Name_QNAME, Boolean.class, MyClassImpl2.class, value);
    }
}

这里的问题是每个方法名称都与一个类名称匹配。没有说“创建接口的属性”的方法,这将允许一种方法适用于该接口的所有实现。同样,无法修改Factory。实际上,唯一可以修改的类是该接口:

public interface MyInterface {
    JAXBElement<String> getAttribute1Name;
    void setAttribute1Name(String attribute1Value);
    JAXBElement<Boolean> getAttribute2Name;
    void setAttribute2Name(Boolean attribute2Value);
}

这里是生成的2个类(留下了一些在这里不相关的xml标记)

public class MyClassImpl1 implements MyInterface {
    private String attribute1Name;
    private Boolean attribute2Name;

    public JAXBElement<String> getAttribute1Name() {
        return attribute1Name;
    }

    public void setAttribute1Name(JAXBElement<String> value) {
        this.attribute2Name = value;
    }

    public JAXBElement<Boolean> getAttribute2Name() {
        return attribute2Name;
    }

    public void setAttribute2Name(JAXBElement<Boolean> value) {
        this.attribute2Name = value;
    }
}


public class MyClassImpl2 implements MyInterface {
    private String attribute1Name;
    private Boolean attribute2Name;

    public JAXBElement<String> getAttribute1Name() {
        return attribute1Name;
    }

    public void setAttribute1Name(JAXBElement<String> value) {
        this.attribute2Name = value;
    }

    public JAXBElement<Boolean> getAttribute2Name() {
        return attribute2Name;
    }

    public void setAttribute2Name(JAXBElement<Boolean> value) {
        this.attribute2Name = value;
    }
}

当我对设置器进行接口调用时会发生问题,因为工厂不知道要调用哪种方法(类的特定名称)。

public class AnotherClass {

    public void anotherMethod(MyInterface myInterface) {
        Factory factory = new Factory();
        String value1 = "Some String Value";
        Boolean value2 = true;                
        myInterface.setAttribute1Name(factory.<I need correct method here>(value1));
        myInterface.setAttribute2Name(factory.<I need correct method here>(value2));
    }
}

我也许可以通过反射来做到这一点,但是我对此不太满意,坦率地说,我不喜欢这样做。但这可能是可能起作用的。  将其放在MyInterface上:

default JAXBElement getClassImplJaxbElement(Object attributeValue, String attributeToSet, Factory factory) {

    String factoryMethodName = "create" + this.getClass().getName() + attributeToSet;
    Expression attributeGetter = new Expression(factory, factoryMethodName, new Object[]{attributeValue});
    try {
        attributeGetter.execute();
        return (JAXBElement) attributeGetter.getValue();
    } catch (Exception e) {
        throw new MyRuntimeException(String.format("Failed to create JAXBElement for attribute '%s' and value '%s'.", attributeToSet, attributeValue), e);
    }
}

尤其令人讨厌的是,我必须在要在接口上调用setter的任何地方调用该新方法,这意味着每次反射都很慢。有人知道这样做的方法吗?同样,不能修改ClassImpls也不能修改Factory。

通过.xsd文件和maven插件maven-jaxb22-plugin生成类。通过添加jaxb2-basics插件,我可以生成实现接口的类。

0 个答案:

没有答案