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?
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With