Spring- @ transakcyjny-co się dzieje w tle?

Chcę wiedzieć, co się dzieje, gdy dodajesz metodę @Transactional? Oczywiście Wiem, że Spring zawinie tę metodę w transakcję.

Ale mam następujące wątpliwości:

  1. słyszałem, że Spring tworzy klasę proxy ? Czy ktoś może to wyjaśnić bardziej głębokość . co właściwie znajduje się w klasie proxy? Co się stanie z rzeczywistą klasą? I jak Mogę zobaczyć stworzoną przez Springa klasę proxied
  2. czytam też w Spring docs że:

Notatka: ponieważ ten mechanizm jest oparty na Proxy, tylko 'zewnętrzne' wywołania metody przychodzące przez proxy będą przechwytywane . Oznacza to, że 'self-invocation', tzn. metoda wewnątrz obiektu docelowego wywołująca inną metodę obiektu docelowego, nie doprowadzi do rzeczywistej transakcji w czasie wykonywania, nawet jeśli wywołana metoda jest oznaczona symbolem @Transactional!

Źródło: http://static.springsource.org/spring/docs/2.0.x/reference/transaction.html

Dlaczego tylko zewnętrzne wywołania metod będą w ramach transakcji, a nie metody samoinwokacji?

Author: ROMANIA_engineer, 2009-07-08

4 answers

To jest wielki temat. Doc Spring reference poświęca mu wiele rozdziałów. Polecam lekturę tych o Aspect-Oriented Programming i Transactions, ponieważ deklaratywna obsługa transakcji Springa wykorzystuje AOP u jej podstaw.

Ale na bardzo wysokim poziomie, Spring tworzy proxy dla klas, które deklarują @Transactional na samej klasie lub na członkach. Serwer proxy jest w większości niewidoczny w czasie wykonywania. Daje możliwość zastrzyku przez sprężynę przed, po lub wokół wywołania metody do proxyowanego obiektu. Zarządzanie transakcjami to tylko jeden z przykładów zachowań, które można wykorzystać. Kontrola bezpieczeństwa to kolejne. Możesz również zapewnić własne, do takich rzeczy, jak logowanie. Więc kiedy dodajesz adnotacje do metody za pomocą @ Transactional , Spring dynamicznie tworzy serwer proxy, który implementuje te same interfejsy co klasa, którą komentujesz. A kiedy klienci wykonują połączenia do Twojego obiektu, połączenia są przechwytywane, a zachowania wstrzyknięty przez mechanizm proxy.

Transakcje w EJB działają podobnie.

Jak zauważyłeś, mechanizm proxy działa tylko wtedy, gdy wywołania przychodzą z jakiegoś zewnętrznego obiektu. Kiedy wykonujesz wewnętrzne wywołanie wewnątrz obiektu, tak naprawdę wykonujesz połączenie poprzez odniesienie" this", które omija proxy. Istnieją jednak sposoby obejścia tego problemu. Wyjaśniam jedno podejście w tym poście na forum, w którym używam BeanFactoryPostProcessor aby wstrzyknąć instancję proxy do klas "samo-odwołujących się" w czasie wykonywania. Zapisuję to odniesienie do zmiennej członkowskiej o nazwie " me ". Następnie, jeśli muszę wykonywać połączenia wewnętrzne, które wymagają zmiany statusu transakcji wątku, kieruję połączenie przez proxy (np. " me.someMethod () ".) Post na forum wyjaśnia bardziej szczegółowo. Zauważ, że kod BeanFactoryPostProcessor byłby teraz trochę inny, tak jak został napisany wiosną 1./ align = "left" / Ale mam nadzieję, że da ci to jakiś pomysł. Mam zaktualizowaną wersję, którą prawdopodobnie mógłbym udostępnić.

 201
Author: Rob H,
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-07-08 16:50:34

Kiedy Spring ładuje definicje bean i jest skonfigurowany tak, aby szukać adnotacji @ Transactional, utworzy te obiekty proxy wokół Twojej rzeczywistej bean. Te obiekty proxy są instancjami klas, które są automatycznie generowane w czasie wykonywania. Domyślnym zachowaniem tych obiektów proxy podczas wywoływania metody jest wywołanie tej samej metody na "docelowej" bean (tj. Twojej bean).

Jednak proxy mogą być również dostarczane z interceptorami, a gdy występują te interceptors zostanie wywołany przez proxy, zanim wywoła metodę docelową. W przypadku fasoli docelowej z adnotacją @Transactional, Spring utworzy TransactionInterceptor i przekaże go do wygenerowanego obiektu proxy. Tak więc, gdy wywołujesz metodę z kodu klienta, wywołujesz metodę w obiekcie proxy, który najpierw wywołuje TransactionInterceptor (który rozpoczyna transakcję), który z kolei wywołuje metodę w obiekcie docelowym bean. Kiedy inwokacja się skończy, TransactionInterceptor zatwierdza / wycofuje transakcję. Jest przejrzysty dla kodu klienta.

Jeśli chodzi o" zewnętrzną metodę", jeśli twoja bean wywoła jedną ze swoich własnych metod, to nie będzie tego robić przez proxy. Pamiętaj, Wiosna zawija Twoją fasolę w proxy, twoja fasolka nie ma o tym pojęcia. Tylko połączenia z "zewnątrz" Twojej fasoli przechodzą przez proxy.

Czy to pomaga?

 156
Author: skaffman,
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-07-08 16:59:09

Jako osoba wizualna, Lubię ważyć z diagramem sekwencji wzoru proxy. Jeśli nie wiesz jak czytać strzałki, przeczytałem pierwszą tak: Client wykonuje Proxy.method().

  1. Klient wywołuje metodę na celu z jego perspektywy i jest po cichu przechwytywany przez proxy
  2. jeśli zdefiniowany jest aspekt before, proxy go wykona
  3. następnie wykonywana jest rzeczywista metoda (target)
  4. After-return I after-throwing są opcjonalnymi aspektami które są wykonywane po zwróceniu metody i / lub jeśli metoda rzuca exception
  5. Po tym, proxy wykonuje aspekt after (jeśli jest zdefiniowany)
  6. W końcu proxy wraca do klienta wywołującego

Schemat Sekwencji Wzorca Proxy (Pozwolono mi opublikować zdjęcie pod warunkiem, że wspomnę o jego pochodzeniu. Autor: Noel Vaes, strona: www.noelvaes.eu)

 32
Author: progonkpa,
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
2017-02-24 08:48:42

Najprostsza odpowiedź brzmi: w przypadku dowolnej metody deklarowanej przez @ Transactional granica transakcji rozpoczyna się i kończy po zakończeniu metody.

Jeśli używasz wywołania JPA, to wszystkie commity są z tą granicą transakcji. Powiedzmy, że zapisujesz entity1, entity2 i entity3. Teraz podczas zapisywania entity3 występuje wyjątek, a następnie enitiy1 i entity2 są w tej samej transakcji, więc entity1 i entity2 zostaną wycofane z entity3.

Transakcja : (entity1.Zapisz, entity2.Zapisz, entity3.Zapisz). Każdy wyjątek spowoduje wycofanie wszystkich transakcji JPA z DB. wewnętrzne transakcje JPA są wykorzystywane przez Spring.

 8
Author: RoshanKumar Mutha,
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
2018-01-30 09:14:44