【问题标题】:Weaving in toString() implementation with AspectJ使用 AspectJ 编织 toString() 实现
【发布时间】:2013-01-11 19:47:43
【问题描述】:

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

按照this article中的建议,转成annotation风格的aspect config,最终得到如下代码:

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 表明它们实现了 JsonToString 接口,但任何地方都没有 toString() 方法的迹象。

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

关于如何克服这个问题的任何线索?也许一个@Around 建议关于截取java.lang.Object.toString() 执行的切入点,仅适用于包com.mycompany.dto 下的子类?还是一种强制混合发生的方法?

【问题讨论】:

  • 我知道不是你要找的东西,但总的来说,我建议 AOP 应该保留用于架构问题,如事务、重试策略、授权、审计等,而不是更普通的事情,比如 one-班轮toString() 方法。显然它有助于保持你的 toString() 方法 DRY 但它也有点不明显的“魔法”,使代码库更加复杂。
  • @SingleShot 加载时编织和编译时编织之间有很大的区别。如果放在加载时编织的上下文中,我会分享你的建议。但是编译时编织(这就是这个问题的意义所在)是保持代码库 DRY 的一种完全有效且理智的方法。此外,我认为你的说法根本不成立。在执行状态更改操作(例如事务性建议)时,“魔术”比简单的(或应该是)只读的 toString() 方法危险得多。因此,根据您关于“复杂性”的论点,根本不应该使用 AOP。

标签: java aop aspectj tostring dto


【解决方案1】:

我尝试了您的场景并且可以复制该行为,我还尝试了 @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 可能是不可行的,可能只能通过原生方面实现。

【讨论】:

  • 碧菊,谢谢。你是对的,它适用于原生 AspectJ 表示法。您可以从示例中删除 toString2() 方法,因为它不相关并且会混淆其他人吗?然后我会将您的答案标记为正确。谢谢。
猜你喜欢
  • 1970-01-01
  • 2014-10-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-11-24
  • 1970-01-01
相关资源
最近更新 更多