通过注释/字节码编织跟踪所有权/祖先 - 层次结构/组成员资格?

时间:2012-04-23 08:34:20

标签: java annotations aop relationship bytecode-manipulation

在GUI框架中,显式跟踪父/子关系是很常见的 - 给定一个任意的GUI组件,可以向上导航通过“拥有”它的组件的层次结构。

父组件不一定是实际创建子组件的实体,这些关系通常在创建后配置。

我遇到的情况是我感兴趣的创作关系,即一个对象创建另一个。

所涉及的对象属于不同的类,它们之间通常没有继承关系等。

我真的创建了具有id的“主”对象,我希望这些对象创建的所有对象(直接或在n度分离)知道其特定“主”对象的id。 / p>

[该ID实际上仅用于记录目的。 ]

我可以想象这样的事情:

public class Master
{
    @GroupId
    private final long id;
}

@InheritGroupId
public class Foo
{
    public void bar()
    {
        logger.info("I belong to group {}", XXX);
    }
}

对于Master对象,id将在其构造函数中设置。任何用@InheritGroupId标记的类都会在构造以某种方式查找堆栈并查找第一个调用者对象,该对象直接通过@GroupId注释知道其group-id或者在同一个中确定它作为这个类的时尚,也就是那个也用@InheritGroupId标记的类。

然后你将如何访问我不确定的group-id值,在上面的代码中我刚刚在我想要访问它的地方使用了XXX。

我说“以某种方式查找堆栈”,但据我所知,不可能用直接的Java检查这样的堆栈。

也许可以使用不需要堆叠检查的替代结构。或者也许某种AOP字节编织方法可能?

目前我将groupId作为显式构造函数参数传递给我系统中的几乎每个对象。对我来说,所有对象都必须维护一个成员变量,这个变量不是逻辑的一部分,而是纯粹用于记录,这似乎是一种耻辱。

明确地传递groupId确实具有明确指出在低位和我的“主”对象之间建立创建者关系的情况很困难的优势。

如果你有任何想法如何处理我用注释或字节码编织所描述的内容,或者你认为明确地传递group-id实际上是最好的方法,或者你对如何实现有一些完全不同的想法同样的事情,请告诉我。

/乔治

更新:请注意,给定主对象的所有“子”对象都是而不是都是在一个给定的时间点预先创建的,即它不是简单地将group-id设置为某个单例,然后让子对象以某种方式访问​​这个单例,因为它们是集体创建的。

1 个答案:

答案 0 :(得分:0)

我想你想要a per-control-flow aspect。每次在切入点中输入方法时,都会创建方面的实例。每次退出控制流时,它都会被取消引用。它本质上是线程本地的,它将在您想要初始化时准确创建。这只是一个草图,但我想你会想要这样的东西:

aspect GetId percflow(callsFromMaster()) {

    private long id;

    pointcut callsFromMaster() : within(Master.*);
    pointcut childConstructors() : cflow(callsFromMaster()) && execution(Foo.new.(..));

    before(Master master) : callsFromMaster() && this(master) {
        this.id = master.getId();
    }

    after(Foo child) : childConstructors() && this(child) {
        child.id = this.id;
    }

}

我将其读作:每次从Master方法输入调用的控制流时,请创建此方面的新实例。在每次呼叫之前,请保存ID。在同一个控制流程中,每次创建新的Foo时,都会将ID从当前Master复制到新的Foo。