Вплетение в реализацию toString() с помощью AspectJ

Попытка сплести метод toString() по умолчанию для большого количества DTO, используя только сплетение во время компиляции. Цель состоит в том, чтобы вернуть представление 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 для результирующих классов показывает, что они реализуют интерфейс JsonToString, но нигде нет признаков метода toString().

Если я изменю имя метода на то, что не конфликтует с Object.toString() (например, toString2()), метод действительно будет добавлен.

Любые подсказки о том, как преодолеть это? Может быть, совет @Around по pointcut, который перехватывает выполнение java.lang.Object.toString(), только для дочерних классов ниже пакета com.mycompany.dto? Или способ заставить миксин произойти?


person raulk    schedule 11.01.2013    source источник
comment
Не то, что вы ищете, я знаю, но в целом я предлагаю, чтобы АОП был зарезервирован для архитектурных проблем, таких как транзакции, стратегии повторных попыток, авторизация, аудит и т. д., а не для более приземленных вещей, таких как однострочный метод toString(). Очевидно, это помогает сохранить ваши toString() методы DRY, но это также немного неочевидной магии. это усложняет кодовую базу.   -  person SingleShot    schedule 13.01.2013
comment
@SingleShot Существует большая разница между переплетением во время загрузки и переплетением во время компиляции. Я разделяю ваше предложение, если оно помещено в контекст плетения во время загрузки. Но переплетение во время компиляции (о чем этот вопрос) — это совершенно правильный и разумный способ сохранить вашу кодовую базу СУХОЙ. Более того, я не думаю, что ваше утверждение вообще справедливо. Магия гораздо более опасна при выполнении операций изменения состояния (например, транзакционных советов), чем простой метод toString(), который (или должен быть) доступен только для чтения. Итак, следуя вашему аргументу об усложнении, АОП вообще никогда не должен использоваться.   -  person raulk    schedule 14.01.2013


Ответы (1)


Я попробовал ваш сценарий и смог воспроизвести поведение, я также пробовал комбинации @DeclareMixin вместо @DeclareParent и тоже не смог заставить это работать. Что сработало для меня, так это использовать собственный аспект таким образом:

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

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

Я предполагаю, что это может быть невозможно с использованием @AspectJ и может быть возможно только с помощью собственных аспектов.

person Biju Kunjummen    schedule 11.01.2013
comment
Биджу, спасибо. Вы правы, он работает с родной нотацией AspectJ. Можете ли вы удалить метод toString2() из своего примера, так как он не имеет значения и может запутать других? Тогда я отмечу ваш ответ как правильный. Спасибо. - person raulk; 13.01.2013