Czy istnieje sposób, aby statycznie / globalnie zażądać kopii ApplicationContext w aplikacji Spring?
Zakładając, że główna klasa uruchamia się i inicjuje kontekst aplikacji, czy musi przekazywać to przez stos wywołań do dowolnych klas, które tego potrzebują, czy też istnieje sposób, aby klasa mogła zapytać o wcześniej utworzony kontekst? (Co, jak zakładam, musi być singletonem?)
źródło
instance()
jako fabryki. Myślę jednak, że najpierw pozwalam, aby cały kod poza kontenerem uzyskał dostęp do kontenera jako pierwszy. Następnie ten kod może żądać obiektów z kontenera.Możesz wdrożyć
ApplicationContextAware
lub po prostu użyć@Autowired
:SpringBean
zostanieApplicationContext
wstrzyknięty, w którym ta fasola jest tworzona. Na przykład, jeśli masz aplikację internetową o dość standardowej hierarchii kontekstów:i
SpringBean
jest zadeklarowany w głównym kontekście, zostanie wprowadzony główny kontekst; w przeciwnym razie, jeśli zostanie zadeklarowany w kontekście MVC, zostanie wstrzyknięty kontekst MVC.źródło
@Inject
teżOto dobry sposób (nie mój, oryginalne odniesienie jest tutaj: http://sujitpal.blogspot.com/2007/03/accessing-spring-beans-from-legacy-code.html
Użyłem tego podejścia i działa dobrze. Zasadniczo jest to prosta fasola, która zawiera (statyczne) odniesienie do kontekstu aplikacji. Odwołując się do niego w wiosennej konfiguracji, jest on inicjowany.
Spójrz na oryginalny ref, to jest bardzo jasne.
źródło
getBean
z kodu uruchamianego podczas testu jednostkowego, ponieważ kontekst sprężyny nie zostanie skonfigurowany, zanim poprosisz o to. To stan wyścigu, w który właśnie uderzyłem dzisiaj po 2 latach udanego stosowania tego podejścia.Wierzę, że możesz użyć SingletonBeanFactoryLocator . Plik beanRefFactory.xml zawierałby rzeczywistą aplikacjęContext, wyglądałby mniej więcej tak:
A kod do pobrania fasoli z kontekstu aplikacji z dowolnego miejsca byłby mniej więcej taki:
Zespół wiosenny odradza korzystanie z tej klasy i yadayada, ale dobrze mi to pasuje tam, gdzie z niej korzystałem.
źródło
Przed wdrożeniem jakichkolwiek innych sugestii zadaj sobie następujące pytania ...
Odpowiedzi na te pytania są łatwiejsze w niektórych typach aplikacji (na przykład w aplikacjach internetowych) niż w innych, ale i tak warto je zadać.
Dostęp do ApplicationContext w pewien sposób narusza zasadę wstrzykiwania zależności, ale czasami nie masz dużego wyboru.
źródło
Jeśli używasz aplikacji internetowej, istnieje również inny sposób na dostęp do kontekstu aplikacji bez korzystania z singletonów za pomocą serwletu filtrów i ThreadLocal. W filtrze można uzyskać dostęp do kontekstu aplikacji za pomocą WebApplicationContextUtils i przechowywać kontekst aplikacji lub potrzebne komponenty bean w TheadLocal.
Uwaga: jeśli zapomnisz rozbroić ThreadLocal, będziesz mieć paskudne problemy podczas próby odinstalowania aplikacji! Dlatego powinieneś go ustawić i natychmiast rozpocząć próbę, która rozłączy ThreadLocal w końcowej części.
Oczywiście nadal używa singletonu: ThreadLocal. Ale rzeczywiste ziarna nie muszą już być. Może być nawet objęty zakresem żądań, a to rozwiązanie działa również, jeśli masz wiele WAR w aplikacji z bibliotekami w EAR. Mimo to możesz uznać użycie ThreadLocal za równie złe, jak użycie zwykłych singletonów. ;-)
Być może wiosna już oferuje podobne rozwiązanie? Nie znalazłem, ale nie jestem pewien.
źródło
Źródło: http://sujitpal.blogspot.de/2007/03/accessing-spring-beans-from-legacy-code.html
źródło
Spójrz na ContextSingletonBeanFactoryLocator . Zapewnia statyczne akcesoria do przechwytywania kontekstów Springa, zakładając, że zostały zarejestrowane w określony sposób.
To nie jest ładne i bardziej złożone, niż byś chciał, ale działa.
źródło
Istnieje wiele sposobów na uzyskanie kontekstu aplikacji w aplikacji Spring. Poniżej podano:
Przez ApplicationContextAware :
Tutaj
setApplicationContext(ApplicationContext applicationContext)
metoda otrzymasz kontekst aplikacjiPrzez Autowired :
Tutaj
@Autowired
słowo kluczowe zapewni kontekst aplikacji. Autowired ma jakiś problem. Stworzy to problem podczas testów jednostkowych.źródło
Zauważ, że przechowując dowolny stan z prądu
ApplicationContext
lubApplicationContext
samego w zmiennej statycznej - na przykład przy użyciu wzorca singletonu - sprawisz, że twoje testy będą niestabilne i nieprzewidywalne, jeśli używasz testu wiosennego. Wynika to z tego, że Spring-test buforuje i ponownie wykorzystuje konteksty aplikacji w tej samej maszynie JVM. Na przykład:@ContextConfiguration({"classpath:foo.xml"})
.@ContextConfiguration({"classpath:foo.xml", "classpath:bar.xml})
@ContextConfiguration({"classpath:foo.xml"})
Po uruchomieniu testu A
ApplicationContext
tworzony jest an , a każda implementacja fasoliApplicationContextAware
lub automatyczne połączenieApplicationContext
może zapisywać do zmiennej statycznej.Po uruchomieniu testu B dzieje się to samo, a zmienna statyczna wskazuje teraz na test B.
ApplicationContext
Po uruchomieniu testu C ziarna nie są tworzone, ponieważ
TestContext
(i tutajApplicationContext
) z testu A jest ponownie wykorzystywany. Teraz masz zmienną statyczną wskazującą na innąApplicationContext
niż ta, która aktualnie trzyma ziarna do testu.źródło
Nie wiem, czy będzie to przydatne, ale możesz także uzyskać kontekst podczas inicjalizacji aplikacji. To najwcześniej możesz uzyskać kontekst, nawet przed
@Autowire
.źródło
Proszę to zanotować; poniższy kod utworzy nowy kontekst aplikacji zamiast używać już załadowanego.
Należy również pamiętać, że
beans.xml
powinien być częściąsrc/main/resources
środków wojennych, których jest częściąWEB_INF/classes
, gdzie jak prawdziwa aplikacja zostanie załadowana, o którejapplicationContext.xml
mowa wWeb.xml
.Jest to trudne wspomnieć
applicationContext.xml
ścieżkę wClassPathXmlApplicationContext
konstruktorze.ClassPathXmlApplicationContext("META-INF/spring/applicationContext.xml")
nie będzie w stanie zlokalizować pliku.Lepiej więc użyć istniejącego kontekstu aplikacji za pomocą adnotacji.
źródło
Wiem, że odpowiedź na to pytanie, ale chciałbym udostępnić kod Kotlin, który zrobiłem, aby odzyskać kontekst wiosenny.
Nie jestem specjalistą, dlatego jestem otwarty na krytyków, recenzje i porady:
https://gist.github.com/edpichler/9e22309a86b97dbd4cb1ffe011aa69dd
Teraz kontekst wiosenny jest publicznie dostępny i może wywoływać tę samą metodę niezależnie od kontekstu (testy Junit, komponenty bean, ręcznie tworzone instancje klas), jak w przypadku tego serwletu Java:
źródło
Wykonaj autowire w Spring Bean jak poniżej: @Autowired private ApplicationContext appContext;
będziesz obiektem kontekstu aplikacji.
źródło
Podejście 1: Możesz wstrzyknąć ApplicationContext, implementując interfejs ApplicationContextAware. Link referencyjny .
Podejście 2: Kontekst aplikacji Autowire w dowolnej fasoli zarządzanej wiosną.
Link referencyjny .
źródło