Java 使用AspectJ在toString()实现中编织

Java 使用AspectJ在toString()实现中编织,java,aop,aspectj,tostring,dto,Java,Aop,Aspectj,Tostring,Dto,尝试为大量DTO使用默认的toString()方法,仅使用编译时编织。目标是使用Jackson库返回JSON表示 按照中的建议,将其转换为注释样式的方面配置,最后生成以下代码: public @Aspect class JsonToStringAspect { private interface JsonToString { public String toString(); } public static class JsonToStringImpl

尝试为大量DTO使用默认的toString()方法,仅使用编译时编织。目标是使用Jackson库返回JSON表示

按照中的建议,将其转换为注释样式的方面配置,最后生成以下代码:

public @Aspect class JsonToStringAspect {
    private interface JsonToString {
        public String toString();
    }

    public static class JsonToStringImpl implements JsonToString {
        public String toString() {
            return SingletonJsonEncoder.toJsonString(this);
        }
    }

    @SuppressWarnings("unused")
    @DeclareParents(value = "com.mycompany.dto..*", defaultImpl = JsonToStringImpl.class)
    private JsonToString implementedInterface;
}
在生成的类上运行
javap
表明它们实现了JSONTSING接口,但没有任何地方出现toString()方法的迹象

如果我将方法名称更改为与Object.toString()不冲突的名称(例如,toString()),则该方法将真正添加


关于如何克服这个问题有什么线索吗?可能是关于切入点的
@Around
建议,该切入点拦截java.lang.Object.toString()的执行,仅用于包
com.mycompany.dto
下面的子类?还是一种强迫混入发生的方法?

我尝试了你的场景,可以复制这种行为,我也尝试了
@DeclareMixin
的组合,而不是
@DeclareParent
,但也无法实现。不过,对我来说有效的是以这种方式使用本机aspectj:

public aspect JsonToStringAspect {
    private interface JsonToString {}
    declare parents: com.mycompany.dto.* implements JsonToString;

    public String JsonToString.toString() {
        return "Overridden String through JsonToStringAspect";
    }
}

我猜这在使用
@AspectJ
时可能不可行,可能只有通过本机方面才可行。

Biju,谢谢。您是对的,它使用本机AspectJ表示法。您能否从示例中删除toString 2()方法,因为它不相关并且可能会混淆其他方法?那我就把你的答案标为正确。谢谢。我知道这不是您想要的,但一般来说,我建议AOP应该保留用于事务、重试策略、授权、审核等体系结构问题,而不是像一行程序
toString()
方法这样更普通的事情。显然,它有助于保持您的
toString()
方法,但它还有一点不明显的“魔力”,使代码库更加复杂。@SingleShot加载时编织和编译时编织之间有很大区别。如果将其放在装载时编织的上下文中,我同意您的建议。但是编译时编织(这就是这个问题所涉及的)是保持代码库干燥的一种非常有效和明智的方法。此外,我认为你的说法根本不正确。在执行状态更改操作(例如事务通知)时,“Magic”比简单的只读(或应该是只读)toString()方法危险得多。所以,在你关于“复杂性”的争论之后,AOP根本不应该被使用。