Spring получить текущий ApplicationContext

105

Я использую Spring MVC для своего веб-приложения. Мои бобы записаны в " spring-servlet.xml" файле

Теперь у меня есть класс, MyClassи я хочу получить к нему доступ с помощью Spring bean.

В spring-servlet.xmlя написал следующее

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

Теперь мне нужно получить к нему доступ, используя ApplicationContext

ApplicationContext context = ??

Так что я могу сделать

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

Как это сделать ??

LynAs
источник
3
@Autowired MyClass myClass должен работать!
Mannekenpix

Ответы:

161

Просто введите это ..

@Autowired
private ApplicationContext appContext;

или реализовать этот интерфейс: ApplicationContextAware

гипинани
источник
Возможно, это сработает: stackoverflow.com/questions/11682858/…
gipinani
Следующий ApplicationContextProvider.javaответ выглядит наиболее надежным решением этой проблемы.
Ionut
1
Он каждый раз возвращает NULL. Чтобы упомянуть здесь, что я делаю это внутри обычного класса, который не является ни «@RestController», ни «@Component»
zulkarnain shah
1
Согласно документации Spring, из-за некоторых проблем лучше избегать @Autowired. Вот ссылка spring.io/understanding/application-context . Наилучший вариант - реализовать интерфейс ApplicationContextAware.
Дурджа Араи
89

Я думаю, что эта ссылка демонстрирует лучший способ получить контекст приложения где угодно, даже в классе, отличном от bean. Я считаю это очень полезным. Надеюсь, то же самое и с вами. Ниже приведен абстрактный код этого

Создайте новый класс 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;
    }
}

Добавьте запись в application-context.xml

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

В случае аннотаций (вместо application-context.xml)

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

Получите такой контекст

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

Ура !!

Вивек
источник
1
Я кодировал аналогично Вивеку. Но я избегаю создания нового ApplicationContextProvider () каждый раз, когда мне нужно вызвать getBean () из контекста. Что я сделал, так это статический ApplicationContextProvider.getApplicationContext() метод. Затем, когда приходит время нуждаться в текущем контексте приложения, я ApplicationContextProvider appContext = ApplicationContextProvider.getApplicationContext()
вызываю
1
Да, Панини Лунчер, это все равно было бы хорошо. По вашему предложению я изменю его таким образом. :)
Вивек
4
Добавить @Componentв ApplicationContextProviderконфигурации может избежать вaplication-context.xml
bluearrow
1
Примечание: получатель и установщик контекста должны быть синхронизированы. Вы избежите головной боли, особенно при модульных / интеграционных тестах. В моем случае аналогичный ApplicationContextProvider содержал старый контекст (из предыдущего интеграционного теста), который вызывал множество сложных ошибок.
Oleksandr_DJ
44

Если вам нужно получить доступ к контексту из HttpServlet, который сам по себе не создается Spring (и поэтому ни @Autowire, ни ApplicationContextAware не будут работать) ...

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

или

SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(this);

Что касается некоторых других ответов, подумайте дважды, прежде чем сделать это:

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

... поскольку это не дает вам текущий контекст, а создает для вас еще один его экземпляр. Это означает, что 1) значительный фрагмент памяти и 2) компоненты не используются совместно этими двумя контекстами приложения.

Ярослав Заруба
источник
SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext (this) - выполнил работу за меня в методе init () фильтра действий портлета Liferay.
Игорь Байбородин
Замечательно, processInjectionBasedOnCurrentContext выполнил всю необходимую мне работу. Большое спасибо @Jaroslav
Jad B.
ApplicationContextAware ДЕЙСТВИТЕЛЬНО работает для меня, когда он аннотируется с помощью @Component, как в решении Vivek (я инициализирую контекст Spring вручную, расширяя AbstractContextLoaderInitializer / createRootApplicationContext)
hello_earth
Будьте осторожны ... SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext (this); не происходит сразу, поэтому вы не можете использовать его, например, в качестве первой строки в конструкторе.
SledgeHammer
Это отлично работает в классическом веб-приложении Java (не управляемом Spring-mvc).
lainatnavi
31

Если вы реализуете класс, экземпляр которого не создается Spring, например JsonDeserializer, вы можете использовать:

WebApplicationContext context = ContextLoader.getCurrentWebApplicationContext();
MyClass myBean = context.getBean(MyClass.class);
Жимек
источник
8
Мне это не подходит. Мой класс не в контексте Spring. Я пытался использовать ваш код, но он дал мне нулевой ответ. Я говорю оContextLoader.getCurrentWebApplicationContext()
Р. Карлусе
9

Добавьте это в свой код

@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;

Это просто добавит myClass в ваше приложение

Хитеш Кумар
источник
6

на основе ответа Вивека, но я думаю, что было бы лучше:

@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);
    }
}

Запись из метода экземпляра в статическое поле - плохая практика и опасна, если манипулируют несколькими экземплярами.

Хуан
источник
Есть org.springframework.core.io.ContextResourceинтерфейс. Я бы предложил выбрать другое имя для внутреннего класса, ContextResourceчтобы избежать беспорядка.
Александр Радченко
@AlexanderRadchenko Хорошо, я изменил его на InnerContextResource
Хуан
1

Есть много способов получить контекст приложения в приложении Spring. Они приведены ниже:

  1. Через 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;
    }
    }

Здесь setApplicationContext(ApplicationContext applicationContext)вы получите applicationContext

  1. Через Autowired :

    @Autowired
    private ApplicationContext applicationContext;

Здесь @Autowiredключевое слово предоставит applicationContext.

Для получения дополнительной информации посетите эту ветку

Спасибо :)

Md. Sajedul Karim
источник
0

Другой способ - внедрить applicationContext через сервлет.

Это пример того, как внедрять зависимости при использовании веб-сервисов 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>

Альтернативный способ - добавить контекст приложения в ваш web.xml, как показано ниже.

<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>

По сути, вы пытаетесь указать сервлету, что он должен искать компоненты, определенные в этих файлах контекста.

всингх
источник
0

Шаг 1. Добавьте следующий код в класс

@Autowired
private ApplicationContext _applicationContext;

Шаг 2 : напишите получатель и установщик

Шаг 3 : определите autowire = "byType" в XML-файле, в котором определен компонент

Камлеш Пауникар
источник
0

Даже после добавления @Autowire, если ваш класс не является RestController или классом конфигурации, объект applicationContext получал нулевое значение. Пытался создать новый класс с помощью ниже, и он работает нормально:

@Component
public class SpringContext implements ApplicationContextAware{

   private static ApplicationContext applicationContext;

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

затем вы можете реализовать метод получения в том же классе в соответствии с вашими потребностями, например, получить ссылку на реализованный класс:

    applicationContext.getBean(String serviceName,Interface.Class)
Аман Малхотра
источник
-11
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("/spring-servlet.xml");

Затем вы можете получить bean-компонент:

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

Ссылка: springbyexample.org

PraZ
источник
25
Этот ответ не дает вам текущего контекста, он скорее создает другой экземпляр.
Ярослав Заруба