Подтвердить что ты не робот

Как перехватить вызов метода со стандартными функциями Java (без AspectJ и т.д.)?

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

Я пытался использовать динамические прокси, но, насколько мне известно, это работает только для классов, реализующих некоторый интерфейс. Но у MyClass нет такого интерфейса.

Есть ли другой способ, помимо реализации класса-оболочки, который делегирует все вызовы члену, который является экземпляром MyClass или использует AOP?

4b9b3361

Ответ 1

Как вы заметили, вы не можете использовать динамические прокси JDK (без интерфейса), но используя Spring и CGLIB (JAR включен с Spring), вы можете сделать следующее:

public class Foo
{
    public void setBar()
    {
        throw new UnsupportedOperationException("should not go here");
    }

    public void redirected()
    {
        System.out.println("Yiha");
    }
}

Foo foo = new Foo();
ProxyFactory pf = new ProxyFactory(foo);

pf.addAdvice(new MethodInterceptor()
{
    public Object invoke(MethodInvocation mi) throws Throwable
    {
        if (mi.getMethod().getName().startsWith("set"))
        {
            Method redirect = mi.getThis().getClass().getMethod("redirected");
            redirect.invoke(mi.getThis());
        }
        return null;
    }
});

Foo proxy = (Foo) pf.getProxy();
proxy.setBar(); // prints "Yiha"

Ответ 2

Если вы готовы сделать что-то действительно уродливое, посмотрите:

http://docs.oracle.com/javase/7/docs/technotes/guides/jpda/

В основном интерфейс отладчика должен позволять вам присоединяться как отладчик и, следовательно, перехватывать вызовы. Имейте в виду, я думаю, что это плохая идея действительно, но вы спросили, возможно ли это.

Ответ 3

Java не имеет каких-либо реальных языковых возможностей для перехвата метода (не уверен, что какой-либо статический язык делает)

Мне вроде как нравится идея использования интерфейса отладчика, это просто означает.

Я думаю, что короткий ответ, который вам нужен: Нет, нет способа перехватить вызов метода в Java без фактической замены класса с использованием прокси-сервера или обертки.

Примечание. Библиотеки AOP просто делают это автоматически.

Ответ 4

Я только что разработал небольшую основу для этой цели. Вы можете проверить это: http://code.google.com/p/java-interceptor/ (используйте svn для проверки).

Ответ 5

Некоторые из гуру Java могут на него нагнояться, но у меня был хороший успех, избегая при этом примитивных типов и сеттеров. Мой класс выглядит следующим образом:

class Employee extends SmartPojo {
    public SmartString name;
    public SmartInt age;
}

Вы заметите две вещи: 1. все открыто. 2. Нет конструктора.

Магия происходит в SmartPojo, которая ищет любое поле, которое реализует интерфейс "Smart" и инициализирует его. Поскольку это не примитивный (и не последний класс), я могу добавить методы set() и get() для всех полей в любой точке моей модели в одном месте. Таким образом, нет никаких утилизаторов/геттеров, это потрясающе просто добавить уведомление (также в одном месте) и т.д.

Правда, это больше не POJO, а не Bean в большинстве случаев, но я обнаружил, что эти старые идеи ограничивают меня больше, чем помогают. YMMV.

Ответ 7

  • Почему ваш класс не может реализовать интерфейс? Вы можете просто извлечь из него какой-то интерфейс, содержащий все методы, которые вы хотите перехватить, и использовать динамический механизм прокси. Это также хорошая практика программирования для кода с интерфейсами, а не с классами.

  • Вы можете использовать инфраструктуру Spring с возможностями Spring AOP (которые используют динамические прокси внутри) для этого. Вам просто нужно определить свой класс как Spring bean в файле конфигурации, и клиенты вашего класса должны будут либо получить свой экземпляр из контекста приложения Spring, либо как зависимость автоматически (путем определения setMyClass ( MyClass mc), например). Оттуда вы можете легко перейти к определению аспекта, который перехватывает все вызовы методов этого класса.

Ответ 8

Для перехвата java-метода invoketion AspectJ - хороший инструмент для использования. Через которые можно эффективно перехватывать звонки, казни и т.д. Я использую тот же инструмент для перехвата вызовов java-метода.      Мы можем применять аспекты pointsuts ansd для перехвата любых вызовов java-метода.  для простой информации читайте this