Weaving in toString() implementation with AspectJ

2019-02-16 16:18发布

Trying to weave in a default toString() method for a large number of DTOs, using compile-time weaving only. The goal is to return a JSON representation using the Jackson library.

Followed the suggestions in this article, turned it into annotation-style aspect config, and ended up with the following code:

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;
}

Running javap on the resulting classes shows that they implement the JsonToString interface, but there's no sign of the toString() method anywhere.

If I change the method name to something that doesn't collide with Object.toString() (e.g. toString2()), the method is truly added.

Any clues on how to overcome this? Maybe an @Around advice on a pointcut that intercepts the execution of java.lang.Object.toString(), only for children classes below package com.mycompany.dto? Or a way to force the mixin to happen?

1条回答
聊天终结者
2楼-- · 2019-02-16 16:57

I tried your scenario and could replicate the behavior, I also tried combinations of @DeclareMixin instead of @DeclareParent and could not get that to work either. What worked for me though is to use native aspectj this way:

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

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

I am guessing that this may not be feasible using @AspectJ and may be possible only through native aspects.

查看更多
登录 后发表回答