Jak przechwycić wywołanie metody ze standardowymi funkcjami Javy (bez AspectJ itp.)?

Chcę przechwycić wszystkie wywołania metody do jakiejś klasy MyClass, aby móc reagować na niektóre wywołania setera.

Próbowałem używać dynamicznych proxy, ale z tego co wiem, działa to tylko dla klas implementujących jakiś interfejs. Ale MyClass nie ma takiego interfejsu.

Czy Jest jakiś inny sposób, poza implementacją klasy wrapper, który deleguje wszystkie wywołania do członka, który jest instancją MyClass lub za pomocą AOP?

Author: Tobias Hilka, 2009-02-23

8 answers

Jak zauważyłeś, nie możesz używać dynamicznych proxy JDK (bez interfejsu), ale używając Spring i CGLIB (jar dołączony do Springa), możesz wykonać następujące czynności:

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"
 25
Author: eljenso,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-05-15 02:51:45

Jeśli jesteś gotowy zrobić coś naprawdę brzydkiego, zajrzyj na:

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

Zasadniczo interfejs debuggera powinien umożliwiać podłączanie się jak debugger, a co za tym idzie przechwytywanie połączeń. Pamiętajcie, że to naprawdę zły pomysł, ale pytaliście, czy to możliwe.

 13
Author: Nick Fortescue,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-10-30 22:09:18

Java nie ma żadnych rzeczywistych funkcji językowych dla Przechwytywania metod (nie jestem pewien, czy jakikolwiek statyczny język tak robi)

Podoba mi się pomysł Nicka na użycie interfejsu debuggera, to po prostu złośliwe.

Myślę, że krótka odpowiedź, której potrzebujesz, brzmi: nie istnieje sposób przechwycenia wywołania metody w Javie bez faktycznego zastąpienia klasy za pomocą proxy lub wrappera.

Uwaga: biblioteki AOP sprawiają, że dzieje się to automatycznie.

 2
Author: Gareth Davis,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-05-21 19:19:09

Właśnie opracowałem mały framework do tego celu. Możesz to sprawdzić pod adresem: http://code.google.com/p/java-interceptor/ (Użyj svn aby sprawdzić).

 2
Author: Pierantonio,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-08-21 10:48:06

Niektórzy Guru Javy mogą się na to zmarszczyć, ale udało mi się uniknąć prymitywnych typów i seterów. Moja klasa wygląda tak:

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

Zauważysz dwie rzeczy: 1. wszystko jest publiczne. 2. Brak konstruktora.

Magia dzieje się w SmartPojo, który wyszukuje dowolne pole, które implementuje interfejs "Smart" i inicjalizuje go. Ponieważ nie jest to prymitywna (ani końcowa Klasa), Mogę dodać metody set() I get () dla wszystkich pól w moim model w jednym miejscu . Tak więc żaden setter / getter już nie marnuje, to oszałamiająco proste, aby dodać powiadomienie( również w jednym miejscu), itp.

To prawda, to już nie jest POJO i nie jest to fasola w większości przypadków, ale odkryłem, że te stare pomysły ograniczają mnie bardziej niż pomagają. YMMV.
 1
Author: Aaron Digulla,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-02-23 09:26:15
 0
Author: Miserable Variable,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-02-23 08:55:47
  1. Dlaczego twoja klasa nie może zaimplementować interfejsu? Możesz po prostu wyodrębnić z niego interfejs zawierający wszystkie metody, które chcesz przechwycić i łatwo użyć dynamicznego mechanizmu proxy. Dobrą praktyką programistyczną jest również kodowanie z interfejsami, a nie klasami.

  2. Możesz użyć Spring framework z możliwościami Spring AOP (które używają dynamicznych proxy wewnątrz), aby to zrobić. Będziesz musiał tylko zdefiniować swoją klasę jako fasolkę wiosenną w konfiguracji plik i klienci twojej klasy będą musieli pobrać jego instancję z kontekstu aplikacji Spring lub jako zależność automatycznie (definiując na przykład metodę setMyClass (MyClass mc)). Stamtąd możesz łatwo przejść do definiowania aspektu, który przechwytuje wszystkie wywołania metody do tej klasy.

 0
Author: Stas,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-02-23 09:29:30

Do przechwytywania metody Java invoketion dobrym narzędziem jest AspectJ. Przez które może przechwytywać wywołania mthod, egzekucje itp.. skutecznie. Używam tego samego narzędzia do przechwytywania wywołań metod java. Możemy zastosować pointcuts ansd aspects aby przechwycić dowolne wywołania metod java. aby uzyskać więcej informacji przeczytaj this

 0
Author: SachiN Ware.,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-05-30 06:44:10