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



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

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

有一种情况,我感兴趣的是创建关系,即一个对象创建了另一个对象。

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

实际上,我创建了具有 id 的"主"对象,并且我希望由这些对象创建的所有对象(直接或以 n 度分离)知道其特定"主"对象的 id。

[ 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 注释直接知道其组 id,要么以与该类相同的方式确定它,即也用 @InheritGroupId 标记的类。

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

说"以某种方式查找堆栈",但据我所知,不可能在直接 Java 中像这样检查堆栈。

也许不需要烟囱检查的替代结构是可能的。或者也许某种AOP字节编织方法是可能的?

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

显式传递 groupId 确实具有明确指出以下情况的优势:在低级和我的"主"对象之一之间建立创建者关系是困难的。

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

/乔治

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

我认为您想要每个控制流方面。每次在切入点中输入方法时,都会创建该方面的一个实例。每次退出控制流时,它都会变为未引用状态。它本质上是线程本地的,它将在您想要初始化它时创建。这只是一个草图,但我想你会想要这样的东西:

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 从当前主节点复制到新 Foo。

最新更新