Java MOXy/JAXB“原型模式”-接口继承

Java MOXy/JAXB“原型模式”-接口继承,java,inheritance,interface,jaxb,moxy,Java,Inheritance,Interface,Jaxb,Moxy,我正在尝试使用MOXy/jaxb2.5.0实现四人帮原型模式的一个版本。我希望能够指定项目列表,其中一些项目基于其他项目,即从其他实例复制其数据。为了可重用性,我想创建一个接口,任何可原型对象都应该实现该接口,该接口将为支持该模式所需的属性提供注释 @XmlRootElement(name="IPrototype") public interface IPrototype { /** * Acts as a "copy constructor" */ @Xml

我正在尝试使用MOXy/jaxb2.5.0实现四人帮原型模式的一个版本。我希望能够指定项目列表,其中一些项目基于其他项目,即从其他实例复制其数据。为了可重用性,我想创建一个接口,任何可原型对象都应该实现该接口,该接口将为支持该模式所需的属性提供注释

@XmlRootElement(name="IPrototype")
public interface IPrototype
{
    /**
     * Acts as a "copy constructor"
     */
    @XmlAttribute(name="prototype")
    @XmlIDREF
    public void setPrototype(IPrototype prototype); 

    @XmlAttribute(name="id")
    @XmlID
    public void setId(String id);

    public String getId();
}
理想情况下,实现对象应该是这样的,甚至不必为从接口实现的方法进行注释:

@XmlRootElement(name="Item")
public class Item implements IPrototype
{
    private String m_id = null;

    private String m_data = null;

    public Item()
    {

    }

    /**
     * Never called
     */
    @Override
    public void setPrototype(IPrototype prototype)
    {
        m_data = ((Item)prototype).getData();
    }

    @Override
    public void setId(String id)
    {
        m_id = id;
    }

    @Override
    public String getId()
    {
        return m_id;
    }

    @XmlAttribute(name="data")
    public void setData(String data)
    {
        m_data = data;
    }

    public String getData()
    {
        return m_data;
    }
}
XML看起来像:

<Wrapper>
    <Item id="Item1" data="stuff and things" />
    <Item id="Item2" prototype="Item1" />
</Wrapper>
其中包装器定义为:

@XmlRootElement(name="Wrapper")
public class Wrapper
{
    @XmlElementRef
    private ArrayList<Item> m_items = null; 
}
如果它按照我想要的方式工作,我将得到一个包含两个元素的列表,两个元素都是Item类型,包含相同的数据。但是,MOXy似乎看不到接口上的注释,我得到了一个列表,其中有两个项没有设置XmlID,并且从未调用setPrototype。唯一的解决方案似乎是在Item类中注释setPrototype和setId方法,但这似乎需要将setPrototype的参数类型从IPrototype更改为Item,以便MOXy在正确的类中查找XmlID。不幸的是,这破坏了继承的接口

如果我改为将列表类型改为IPrototype,希望这能让MOXy看到它的注释,那么我会得到相同的行为-null ID,setPrototype从未调用过。无论如何,这并不是我真正想要的,我希望能够约束特定列表中可能包含哪些子类型

我不确定我对接口注释应该如何工作有正确的期望,也许这就是我错误的根源

你有什么想法可以让它工作吗?提前感谢,

史蒂夫

更新:如果我注释Item类,而不更改setPrototype的方法签名(我想我可以接受),我会得到一个包含两个项的列表,正确设置了XmlID,但是setPrototype仍然没有被调用。似乎MOXy正在寻找具有相同XmlID的IPrototype实例,而不是项实例


更新2:而且,如果我将IPrototype转换成一个抽象类,那么一切都可以完美地工作。然而,考虑到Java的单继承模型,这对于旨在补充多继承层次结构的框架对象来说太有限了。所以仍然卡住了。

通过注释项的属性并使用泛型声明setPrototype,我得到了一个可以接受的版本。这是IPrototype中的声明:

public <T> void setPrototype(T prototype);
下面是它在项目中的实现:

@XmlAttribute(name="prototype")
@XmlIDREF
@Override
public <T> void setPrototype(T prototype)
{
    m_data = ((Item)prototype).getData();
}
它可以工作,但我并不特别喜欢重新注释子类。关于这一点,我提出了一个单独的问题,因为在我看来,界面注释的工作方式并不是这样的:


您可以使用MOXy的外部绑定文档覆盖实现类的超类,即从对象到接口IPrototype的项。这将允许您从接口继承映射

有关完整示例,请参见:


但是如果我试图用一个有界类型参数:public void setPrototypeT prototype来声明这个方法,它就不起作用了。我遇到一个异常,抱怨IPrototype没有用@XmlID注释的属性。如果我对这些方法进行注释,则不会调用setPrototype。现在是如此无界。