Весна отримує поточний ApplicationContext


105

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

Тепер у мене є клас, MyClassі я хочу отримати доступ до цього класу за допомогою весняної квасолі

У spring-servlet.xmlя написав наступне

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

Тепер мені потрібно отримати доступ до цього за допомогою ApplicationContext

ApplicationContext context = ??

Так що я можу зробити

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

Як це зробити ??


3
@Autwired MyClass myClass повинен зробити цю роботу!
Mannekenpix

Відповіді:


160

Просто введіть його ..

@Autowired
private ApplicationContext appContext;

або реалізуйте цей інтерфейс: ApplicationContextAware


Може бути , це може працювати: stackoverflow.com/questions/11682858 / ...
gipinani

Наступна ApplicationContextProvider.javaвідповідь виглядає як найбільш надійне рішення для цього.
Іонут

1
Він повертається NULL кожного разу. Згадати тут, що я роблю це всередині нормального класу, який не є ні "@RestController", ні "@Component"
zulkarnain shah

1
Згідно з весняною документацією, краще уникати @Autowired через деякі проблеми. Ось посилання spring.io/understanding/application-context . Найкращим варіантом є реалізація інтерфейсу ApplicationContextAware.
Дурджа Арай

89

Я думаю, що це посилання демонструє найкращий спосіб отримати контекст програми де завгодно, навіть у класі, що не належить до бобів. Я вважаю це дуже корисним. Сподіваюся, це те ж саме для вас. Нижче наведено його абстрактний код

Створіть новий клас 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
Я кодував схожий на Vivek. Але я уникаю створювати новий ApplicationContextProvider () щоразу, коли мені потрібно викликати getBean () з контексту. Що я зробив - це статичний ApplicationContextProvider.getApplicationContext() метод. Потім, коли настав час потрібен поточний контекст програми, я закликаю:ApplicationContextProvider appContext = ApplicationContextProvider.getApplicationContext()
Паніні Ланчер,

1
Так, Пані Ланчер, це все одно було б добре. Згідно з вашою пропозицією, я так зміню. :)
Vivek

4
Додати @Componentв ApplicationContextProviderконфігурації може уникнути вaplication-context.xml
bluearrow

1
Примітка: геттер і задачу контексту повинні бути синхронізовані. Ви уникнете сильного головного болю, спеціально для тестування блоку / інтеграції. У моєму випадку подібний ApplicationContextProvider містив старий контекст (з попереднього тесту на інтеграцію), що спричинило багато хитрощів.
Олександр_DJ

43

У випадку, якщо вам потрібно отримати доступ до контексту зсередини HttpServlet, який сам не інстанціюється Spring (і тому ні @Autowire, ні ApplicationContextAware не працюватимуть) ...

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

або

SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(this);

Щодо деяких інших відповідей, подумайте двічі, перш ніж це зробити:

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

... оскільки це не дає тобі поточного контексту, скоріше, воно створює ще один його примірник. Що означає 1) значну частину пам’яті та 2) боби не поділяються між цими двома контекстами застосування.


SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext (це) - зробив роботу для мене методом init () фільтра дії портлета Liferay.
Ігор Байбородін

Дивовижно, processInjectionBasedOnCurrentContext зробив усі потрібні мені роботи. Велике спасибі @Jaroslav
Jad B.

ApplicationContextAware працює для мене, коли він позначається за допомогою @Component, як у рішенні Vivek (я ініціалізую Весняний контекст вручну за допомогою розширення AbstractContextLoaderInitializer / createRootApplicationContext)
hello_earth

Будьте попереджені ... SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext (це); відбувається не відразу, тому ви не можете використовувати його, наприклад, як перший рядок у конструкторі.
SledgeHammer

31

Якщо ви реалізуєте клас, який не інстанціюється Spring, як JsonDeserializer ви можете використовувати:

WebApplicationContext context = ContextLoader.getCurrentWebApplicationContext();
MyClass myBean = context.getBean(MyClass.class);

8
Це не працює для мене. Мій клас поза контекстом весни. Я намагався використовувати ваш код, але він дав мені нуль як відповідь. Я говорю про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
    private ApplicationContext applicationContext;

Ось @Autowired ключове слово надасть applicationContext.

Для отримання додаткової інформації відвідайте цю тему

Дякую :)


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>

Альтернативним способом є додавання програми Context у свій 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 : Напишіть Getter & Setter

Крок 3 : визначте autowire = "byType" у файлі xml, у якому визначено bean


0

Навіть після додавання @Autowire, якщо ваш клас не є RestController або Configuration Class, об’єкт applicationContext ставав нульовим. Спробував створити новий клас із нижче, і він прекрасно працює:

@Component
public class SpringContext implements ApplicationContextAware{

   private static ApplicationContext applicationContext;

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

потім ви можете реалізувати метод getter у тому ж класі, що відповідає вашим потребам, як отримати посилання на клас реалізованого шляхом:

    applicationContext.getBean(String serviceName,Interface.Class)

-11
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("/spring-servlet.xml");

Потім ви можете отримати квасоля:

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

Довідка: springbyexample.org


25
Ця відповідь не дає вам поточного контексту, скоріше створює інший екземпляр.
Ярослав Заруба
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.