2009-06-28 6 views
25

Можно в простой Java переопределить метод класса программно во время выполнения (или даже создать новый метод)?Отражение Java: как переопределить или сгенерировать методы во время выполнения?

Я хочу, чтобы это сделать, даже если я не знаю классы во время компиляции.

Что я имею в виду именно переопределив во время выполнения:

abstract class MyClass{ 
    public void myMethod(); 
} 

class Overrider extends MyClass{ 
    @Override 
    public void myMethod(){} 
} 

class Injector{ 
    public static void myMethod(){ // STATIC !!! 
    // do actual stuff 
    } 
} 

// some magic code goes here 
Overrider altered = doMagic(
    MyClass.class, Overrider.class, Injector.class); 

Теперь этот розарий ...

altered.myMethod(); 

... назовет Injector.myMethod() вместо подмены .myMethod().

Injector.myMethod() является статическим , потому что, после того, как делать «магию» он вызывается из другого экземпляра класса (это подмены), (так мы можем предотвратить его от доступа локальных полей).

+1

Не могли бы вы рассказать нам, какие объекты вы хотите переопределить? На первый взгляд ваша проблема напоминает мне о цели парадигмы инъекций зависимостей. – akarnokd

ответ

10

Вы можете использовать что-то вроде cglib для генерации кода на лету

8

Для интерфейсов есть java.lang.reflect.Proxy.

Для занятий вам понадобится библиотека сторонних разработчиков или напишите справедливый бит кода. Обычно динамически создавая классы таким образом, нужно создавать макеты для тестирования.

Существует также API-интерфейс инструментария, который позволяет изменять классы. Вы также можете изменять классы с помощью специального загрузчика классов или только файлы классов на диске.

+0

@ T.H.t: На ваш взгляд, может быть применена реорганизация стиля AOP или BCEL в этом случае?Я столкнулся с подобной проблемой в настоящее время и не могу решить, что использовать. – akarnokd

+1

АОП очень общий. Я предпочитаю ASM BCEL. oxbow_lakes упоминает cglib, который я не мог запомнить имя (и не использовал). –

0

Если бы я получил это право, главная проблема, которая касается вас, как пройти статический метод делегата (например, в C#), через метод интерфейса экземпляра.

Вы можете проверить эту статью: A Java Programmer Looks at C# Delegates, в которой показано, как получить ссылку на ваш статический метод и вызвать его. Затем вы можете создать класс-оболочку, который принимает имя статического метода в своем конструкторе и реализует ваш базовый класс для вызова статического метода из метода экземпляра.

8

Я написал article for java.net о том, как прозрачно добавлять инструкции ведения журнала в класс, когда он загружается загрузчиком классов с помощью java-агента.

Он использует библиотеку Javassist для управления байтовым кодом, в том числе с использованием компилятора Javassist для генерации дополнительного байт-кода, который затем вставлен в соответствующее место, а затем полученный класс предоставляется загрузчику классов.

Уточненный вариант доступен с проектом slf4j.

+0

Теперь несколько лет спустя я не буду рекомендовать этот подход. Если вам это нужно, загляните в Аспектно-ориентированное программирование. –

9

В java6 была добавлена ​​возможность преобразования любого уже загруженного класса. Взгляните на changes в пакет java.lang.instrument

+0

Я даже забыл, что этот пакет существует! Благодаря! –

Смежные вопросы