Spring pobiera aktualny ApplicationContext

105

Używam Spring MVC dla mojej aplikacji internetowej. Moje ziarna są zapisane w spring-servlet.xmlpliku " "

Teraz mam klasę MyClassi chcę uzyskać do niej dostęp za pomocą fasoli wiosennej

W tym spring-servlet.xmlnapisałem

<bean id="myClass" class="com.lynas.MyClass" />

Teraz muszę uzyskać dostęp do tego za pomocą ApplicationContext

ApplicationContext context = ??

Więc mogę to zrobić

MyClass myClass = (MyClass) context.getBean("myClass");

Jak to zrobić??

LynAs
źródło
3
@Autowired MyClass myClass powinien wykonać zadanie!
Mannekenpix

Odpowiedzi:

161

Po prostu wstrzyknij to ..

@Autowired
private ApplicationContext appContext;

lub zaimplementuj ten interfejs: ApplicationContextAware

gipinani
źródło
Może to zadziała: stackoverflow.com/questions/11682858/ ...
gipinani
Poniższa ApplicationContextProvider.javaodpowiedź wydaje się być najbardziej niezawodnym rozwiązaniem tego problemu.
Ionut
1
Za każdym razem zwraca NULL. Aby wspomnieć, że robię to w normalnej klasie, która nie jest ani „@RestController”, ani „@Component”
zulkarnain shah
1
Zgodnie z dokumentacją Springa z powodu pewnych problemów najlepiej unikać @Autowired. Oto link spring.io/understanding/application-context . Najlepszą opcją jest wdrożenie interfejsu ApplicationContextAware.
Durja Arai
89

Myślę, że ten link pokazuje najlepszy sposób na uzyskanie kontekstu aplikacji w dowolnym miejscu, nawet w klasie innej niż fasola. Uważam, że jest to bardzo przydatne. Mam nadzieję, że dla ciebie to samo. Poniżej znajduje się jego abstrakcyjny kod

Utwórz nową klasę ApplicationContextProvider.java

package com.java2novice.spring;

import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;

public class ApplicationContextProvider implements ApplicationContextAware{

    private static ApplicationContext context;

    public static ApplicationContext getApplicationContext() {
        return context;
    }

    @Override
    public void setApplicationContext(ApplicationContext ac)
            throws BeansException {
        context = ac;
    }
}

Dodaj wpis w pliku application-context.xml

<bean id="applicationContextProvider"
                        class="com.java2novice.spring.ApplicationContextProvider"/>

W przypadku adnotacji (zamiast application-context.xml)

@Component
public class ApplicationContextProvider implements ApplicationContextAware{
...
}

Uzyskaj taki kontekst

TestBean tb = ApplicationContextProvider.getApplicationContext().getBean("testBean", TestBean.class);

Twoje zdrowie!!

Vivek
źródło
1
Zakodowałem podobnie jak Vivek. Ale unikam tworzenia nowej ApplicationContextProvider () za każdym razem, gdy muszę wywołać metodę getBean () z kontekstu. To, co zrobiłem, to metoda statyczna ApplicationContextProvider.getApplicationContext() . Następnie, gdy ApplicationContextProvider appContext = ApplicationContextProvider.getApplicationContext()
nadejdzie
1
Tak Panini Luncher, to nadal by było dobre. Zgodnie z twoją sugestią zmienię to w ten sposób. :)
Vivek
4
Dodaj @Componentna ApplicationContextProviderkonfiguracji może uniknąć waplication-context.xml
Blue Arrow
1
Uwaga: pobierający i ustawiający kontekst powinny być zsynchronizowane. Unikniesz wielu problemów, szczególnie w przypadku testów jednostkowych / integracji. W moim przypadku podobny ApplicationContextProvider utrzymywał stary kontekst (z poprzedniego testu integracji), który powodował wiele trudnych błędów.
Oleksandr_DJ
43

W przypadku, gdy potrzebujesz uzyskać dostęp do kontekstu z poziomu HttpServlet, który sam nie jest tworzony przez Spring (a zatem ani @Autowire, ani ApplicationContextAware nie będą działać) ...

WebApplicationContext applicationContext = WebApplicationContextUtils.getWebApplicationContext(getServletContext());

lub

SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(this);

Jeśli chodzi o niektóre inne odpowiedzi, zastanów się dwa razy, zanim to zrobisz:

new ClassPathXmlApplicationContext("..."); // are you sure?

... ponieważ nie daje to aktualnego kontekstu, a raczej tworzy dla Ciebie kolejną jego instancję. Oznacza to, że 1) znaczna część pamięci i 2) ziarna nie są współdzielone między tymi dwoma kontekstami aplikacji.

Jaroslav Záruba
źródło
SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext (this) - wykonał zadanie za mnie w metodzie init () filtru akcji portletu Liferay.
Igor Baiborodine
Wspaniale, procesInjectionBasedOnCurrentContext wykonał wszystko, czego potrzebowałem. Wielkie dzięki @Jaroslav
Jad B.
ApplicationContextAware DZIAŁA dla mnie, gdy jest opatrzony adnotacją @Component, tak jak w rozwiązaniu Vivek (inicjuję kontekst Spring ręcznie przez rozszerzenie AbstractContextLoaderInitializer / createRootApplicationContext)
hello_earth
Uważaj ... SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext (this); nie dzieje się natychmiast, więc nie możesz na przykład użyć go jako pierwszego wiersza w konstruktorze.
SledgeHammer
31

Jeśli implementujesz klasę, która nie jest tworzona przez Spring, na przykład JsonDeserializer, możesz użyć:

WebApplicationContext context = ContextLoader.getCurrentWebApplicationContext();
MyClass myBean = context.getBean(MyClass.class);
rzymek
źródło
8
Na mnie to nie działa. Moja klasa jest poza kontekstem wiosny. Próbowałem użyć twojego kodu, ale w odpowiedzi otrzymałem wartość null . Mówię oContextLoader.getCurrentWebApplicationContext()
R. Karlus
9

Dodaj to do swojego kodu

@Autowired
private ApplicationContext _applicationContext;

//Add below line in your calling method
MyClass class = (MyClass) _applicationContext.getBean("myClass");

// Or you can simply use this, put the below code in your controller data member declaration part.
@Autowired
private MyClass myClass;

Spowoduje to po prostu wstrzyknięcie myClass do Twojej aplikacji

Hitesh Kumar
źródło
6

w oparciu o odpowiedź Viveka, ale myślę, że lepiej:

@Component("applicationContextProvider")
public class ApplicationContextProvider implements ApplicationContextAware {

    private static class AplicationContextHolder{

        private static final InnerContextResource CONTEXT_PROV = new InnerContextResource();

        private AplicationContextHolder() {
            super();
        }
    }

    private static final class InnerContextResource {

        private ApplicationContext context;

        private InnerContextResource(){
            super();
        }

        private void setContext(ApplicationContext context){
            this.context = context;
        }
    }

    public static ApplicationContext getApplicationContext() {
        return AplicationContextHolder.CONTEXT_PROV.context;
    }

    @Override
    public void setApplicationContext(ApplicationContext ac) {
        AplicationContextHolder.CONTEXT_PROV.setContext(ac);
    }
}

Zapisywanie z metody instancji do pola statycznego jest złą praktyką i niebezpiecznym, jeśli manipuluje się wieloma instancjami.

Juan
źródło
Jest org.springframework.core.io.ContextResourceinterfejs. Proponuję wybrać inną nazwę dla klasy wewnętrznej, ContextResourceaby uniknąć bałaganu.
Alexander Radchenko
@AlexanderRadchenko Ok, zmieniłem to na InnerContextResource
Juan
1

Istnieje wiele sposobów uzyskania kontekstu aplikacji w aplikacji Spring. Poniżej podano:

  1. Za pośrednictwem ApplicationContextAware :

    import org.springframework.beans.BeansException;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.ApplicationContextAware;
    
    public class AppContextProvider implements ApplicationContextAware {
    
    private ApplicationContext applicationContext;
    
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }
    }

Tutaj setApplicationContext(ApplicationContext applicationContext)otrzymasz metodę applicationContext

  1. Przez Autowired :

    @Autowired
    private ApplicationContext applicationContext;

Tutaj @Autowiredsłowo kluczowe zapewni applicationContext.

Więcej informacji znajdziesz w tym wątku

Dzięki :)

Md. Sajedul Karim
źródło
0

Innym sposobem jest wstrzyknięcie applicationContext przez serwlet.

To jest przykład, jak wstrzyknąć zależności podczas korzystania z usług internetowych Spring.

<servlet>
        <servlet-name>my-soap-ws</servlet-name>
        <servlet-class>org.springframework.ws.transport.http.MessageDispatcherServlet</servlet-class>
        <init-param>
            <param-name>transformWsdlLocations</param-name>
            <param-value>false</param-value>
        </init-param>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:my-applicationContext.xml</param-value>
        </init-param>
        <load-on-startup>5</load-on-startup>

</servlet>

Alternatywnym sposobem jest dodanie kontekstu aplikacji do pliku web.xml, jak pokazano poniżej

<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>
        /WEB-INF/classes/my-another-applicationContext.xml
        classpath:my-second-context.xml
    </param-value>
</context-param>

Zasadniczo próbujesz powiedzieć apletowi, że powinien szukać ziaren zdefiniowanych w tych plikach kontekstowych.

vsingh
źródło
0

Krok 1 : Wprowadź następujący kod w klasie

@Autowired
private ApplicationContext _applicationContext;

Krok 2 : Napisz Getter & Setter

Krok 3 : zdefiniuj autowire = "byType" w pliku xml, w którym zdefiniowany jest bean

Kamlesh Paunikar
źródło
0

Nawet po dodaniu @Autowire, jeśli twoja klasa nie jest RestController lub Configuration Class, obiekt applicationContext przychodził z wartością null. Próbowałem utworzyć nową klasę z poniższymi i działa dobrze:

@Component
public class SpringContext implements ApplicationContextAware{

   private static ApplicationContext applicationContext;

   @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws 
     BeansException {
    this.applicationContext=applicationContext;
   }
 }

możesz następnie zaimplementować metodę pobierającą w tej samej klasie, jak na swoje potrzeby, na przykład pobranie odwołania do klasy implementowanej przez:

    applicationContext.getBean(String serviceName,Interface.Class)
Aman Malhotra
źródło
-11
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("/spring-servlet.xml");

Następnie możesz odzyskać fasolę:

MyClass myClass = (MyClass) context.getBean("myClass");

Źródła : springbyexample.org

PraZ
źródło
25
Ta odpowiedź nie podaje aktualnego kontekstu, a raczej tworzy inną instancję.
Jaroslav Záruba