Модификация класса в runtime с помощью Java Reflection API
Есть ли возможность модифицировать класс, добавив в него новый метод (или копию метода, с другими параметрами в аннотации и другим именем) в runtime с помощью Java Reflection API или аналогов?
Ответы (1 шт):
Краткий ответ:
Нет, с помощью рефлексии изменить существующий класс нельзя.
Развернутый ответ:
Достичь интересующей вас задачи можно за счет изменения содержимого класса на этапе комплияции (этап, на котором исходный код преобразуется в байт-код).
Самый простой способ встроиться в процесс компиляции - это использование механизма Pluggable Annotation Processing API:
- создается аннотация с временем жизни до этапа компиляции (
RetentionPolicy.SOURCE); - создается обработчик, который "подписывается" на эту аннотацию:
- обработчик расширяет class
javax.annotation.processing.AbstractProcessor; - обработчик будет вызываться компилятором каждый раз, когда он будет встречать элемент (класс / метод / поле / ...), на который навешана данная аннотация;
- в рамках этого обрабочика, как раз, и происходит модификация кода;
- обработчик расширяет class
- созданная аннотация навешивается на элемент (класс / метод / поле / ...), который вы хотите модернизировать на этапе компиляции в своем обработчике.
Использование этого механизма на примере создания Builder'а для класса можете найти здесь. Среди крупных проектов, полагающихся на эту технологию можно отметить Lombok.
Дополнение:
Если, все-таки, вам было бы достаточно просто изменить поведение методов существующего класса, то можно было бы воспользоваться технологией динамических прокси классов.
Эта технология базируется на создании класса наследника того, что укажете вы:
- оригинальный экземпляр класса хранится в виде поля у этого класса;
- в рамках класса переопределяются методы;
- часть методов просто вызывают идентичные методы оригинального экземпляра класса (т.е. происходит "проксирование" вызовов);
- часть методов модифицируется вами.
Среди готовых оберток для использования этой технологии можно выделить следующие: