Переопределить класс с помощью byte-buddy

Я хочу переопределить класс Source, который уже определен в существующей структуре. Я хочу автоматически заменить исходные экземпляры класса Source моим расширенным классом. У меня нет доступа к коду, который создает объекты Source, поэтому подстановка класса должна выполняться автоматически. Можно ли это сделать с помощью byte-buddy?

    ByteBuddyAgent.install();
    Source source = new ByteBuddy()
            .subclass(Source.class)
            .method(named("hello")).intercept(MethodDelegation.to(Target.class))
            .defineMethod("myNewMethod", void.class).intercept(MethodDelegation.to(Target.class))
            .make()
            .load(Source.class.getClassLoader(),
                    ClassReloadingStrategy.fromInstalledAgent())
            .getLoaded()
            .newInstance();

person Liviu Carausu    schedule 14.03.2017    source источник


Ответы (1)


Можно переопределить класс с помощью Byte Buddy. Для этого вы должны использовать методы ByteBuddy::redefine или ByteBuddy::rebase вместо создания подклассов. Самый канонический способ использования этих функций — определить агент Java, для которого вы можете использовать файл AgentBuilder.

person Rafael Winterhalter    schedule 15.03.2017
comment
Ok. Спасибо ! Однако добавление новых методов должно быть разрешено только в случае подкласса, иначе я получаю ** Исключение в потоке main java.lang.UnsupportedOperationException: сбой переопределения класса: попытка изменить схему (добавить/удалить поля) ** - person Liviu Carausu; 15.03.2017
comment
На самом деле я пытаюсь сделать следующее: у меня есть экземпляр объекта, который реализует данный интерфейс. Текущая реализация создает новый объект с тем же интерфейсом и делегирует большинство вызовов исходному объекту. Он также изменяет некоторые методы и добавляет некоторые методы. Чего я хочу добиться, так это использовать инструменты, чтобы мне не приходилось всегда добавлять новый метод к моему декорированному объекту каждый раз, когда изменяется исходный интерфейс. Я думаю, что лучше всего использовать подклассы и делегировать все методы интерфейса с помощью method(isDeclaredBy(Source.class)) исходному - person Liviu Carausu; 15.03.2017
comment
Вы не можете заменить класс с помощью агента Java, вы можете только добавить собственную логику диспетчеризации внутри метода. Я рекомендую вам изучить компонент Advice. - person Rafael Winterhalter; 15.03.2017
comment
Хорошо, извините, я думаю, что мне агент вообще не нужен. Я создам только подкласс и по умолчанию перенаправлю все методы экземпляра на исходный объект. Все методы, которые мне нужно переписать или добавить, будут обрабатываться через defineMethod(новые методы) или метод(named(..)).intercept.() - существующие методы - person Liviu Carausu; 15.03.2017