Как перехватить вызов метода со стандартными функциями Java (без AspectJ и т.д.)?
Я хочу перехватить все вызовы методов для некоторого класса MyClass, чтобы иметь возможность реагировать на некоторые вызовы setter.
Я пытался использовать динамические прокси, но, насколько мне известно, это работает только для классов, реализующих некоторый интерфейс. Но у MyClass нет такого интерфейса.
Есть ли другой способ, помимо реализации класса-оболочки, который делегирует все вызовы члену, который является экземпляром MyClass или использует AOP?
Ответы
Ответ 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.
Ответ 6
В AspectJ мало магии. Вы можете написать свой собственный агент. http://java.sun.com/javase/6/docs/api/java/lang/instrument/package-summary.html кажется хорошей отправной точкой.
Ответ 7
-
Почему ваш класс не может реализовать интерфейс? Вы можете просто извлечь из него какой-то интерфейс, содержащий все методы, которые вы хотите перехватить, и использовать динамический механизм прокси. Это также хорошая практика программирования для кода с интерфейсами, а не с классами.
-
Вы можете использовать инфраструктуру Spring с возможностями Spring AOP (которые используют динамические прокси внутри) для этого. Вам просто нужно определить свой класс как Spring bean в файле конфигурации, и клиенты вашего класса должны будут либо получить свой экземпляр из контекста приложения Spring, либо как зависимость автоматически (путем определения setMyClass ( MyClass mc), например). Оттуда вы можете легко перейти к определению аспекта, который перехватывает все вызовы методов этого класса.
Ответ 8
Для перехвата java-метода invoketion AspectJ - хороший инструмент для использования. Через которые можно эффективно перехватывать звонки, казни и т.д. Я использую тот же инструмент для перехвата вызовов java-метода. Мы можем применять аспекты pointsuts ansd для перехвата любых вызовов java-метода. для простой информации читайте this