Spring obter o ApplicationContext atual


105

Estou usando Spring MVC para meu aplicativo da web. Meus grãos estão escritos no spring-servlet.xmlarquivo " "

Agora eu tenho uma aula MyClasse quero acessá-la usando Spring Bean

No spring-servlet.xmleu escrevi a seguir

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

Agora eu preciso acessar isso usando ApplicationContext

ApplicationContext context = ??

Para que eu possa fazer

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

Como fazer isso??


3
@Autowired MyClass myClass deve fazer o trabalho!
Mannekenpix

Respostas:


161

Basta injetar ..

@Autowired
private ApplicationContext appContext;

ou implemente esta interface: ApplicationContextAware


Talvez isso possa funcionar: stackoverflow.com/questions/11682858/…
gipinani

A seguinte ApplicationContextProvider.javaresposta parece ser a solução mais confiável para isso.
Ionut

1
Ele está retornando NULL sempre. Para mencionar aqui que estou fazendo isso dentro de uma classe normal que não é um "@RestController" nem um "@Component"
zulkarnain shah

1
De acordo com a documentação do Spring, é melhor evitar @Autowired devido a alguns problemas. Aqui está o link spring.io/understanding/application-context . A melhor opção é implementar a interface ApplicationContextAware.
Durja Arai

89

Acho que este link demonstra a melhor maneira de obter o contexto do aplicativo em qualquer lugar, mesmo na classe não-bean. Acho muito útil. Espero que seja o mesmo para você. A seguir está o código abstrato dele

Crie uma nova classe 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;
    }
}

Adicione uma entrada em application-context.xml

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

No caso de anotações (em vez de application-context.xml)

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

Obtenha o contexto como este

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

Felicidades!!


1
Eu codifiquei semelhante ao Vivek. Mas evito criar um novo ApplicationContextProvider () sempre que preciso chamar getBean () a partir do contexto. O que fiz foi ter um ApplicationContextProvider.getApplicationContext() método estático . Então, quando é hora de precisar do contexto do aplicativo atual, invoco:ApplicationContextProvider appContext = ApplicationContextProvider.getApplicationContext()
Panini Luncher

1
Sim Panini Luncher, isso ainda seria bom. De acordo com sua sugestão, vou mudar dessa forma. :)
Vivek

4
Adicionar @Componentna ApplicationContextProviderconfiguração pode evitar emaplication-context.xml
bluearrow

1
Nota: getter e setter de contexto devem ser sincronizados. Você evitará muitas dores de cabeça especialmente para testes de unidade / integração. No meu caso, ApplicationContextProvider semelhante continha um contexto antigo (do teste de integração anterior) que causou muitos bugs complicados.
Oleksandr_DJ

43

Caso você precise acessar o contexto de dentro de um HttpServlet que não é instanciado pelo Spring (e, portanto, nem @Autowire nem ApplicationContextAware funcionarão) ...

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

ou

SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(this);

Quanto a algumas das outras respostas, pense duas vezes antes de fazer isso:

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

... já que isso não fornece o contexto atual, em vez disso, cria outra instância dele para você. O que significa 1) bloco significativo de memória e 2) beans não são compartilhados entre esses dois contextos de aplicativo.


SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext (this) - fez o trabalho para mim no método init () do filtro de ação do portlet Liferay.
Igor Baiborodine

Incrível, o processInjectionBasedOnCurrentContext fez todo o trabalho que eu precisava. Muito obrigado @Jaroslav
Jad B.

ApplicationContextAware FUNCIONA para mim, quando é anotado com @Component como na solução de Vivek (estou inicializando o contexto Spring manualmente através da extensão de AbstractContextLoaderInitializer / createRootApplicationContext)
hello_earth

Esteja avisado ... SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext (this); não acontece imediatamente, então você não pode usá-lo como a primeira linha em seu construtor, por exemplo.
SledgeHammer

31

Se você está implementando uma classe que não é instanciada pelo Spring, como um JsonDeserializer, você pode usar:

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

8
Não funciona para mim. Minha classe está fora do contexto do Spring. Tentei usar seu código, mas me deu um null como resposta. Estou falando deContextLoader.getCurrentWebApplicationContext()
R. Karlus

9

Adicione isso ao seu código

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

Isso simplesmente injetará myClass em seu aplicativo


6

com base na resposta de Vivek, mas acho que o seguinte seria melhor:

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

Gravar de um método de instância em um campo estático é uma prática ruim e perigosa se várias instâncias estiverem sendo manipuladas.


Existe org.springframework.core.io.ContextResourceinterface. Eu sugeriria escolher um nome diferente para a classe interna ContextResourceapenas para evitar confusão.
Alexander Radchenko

@AlexanderRadchenko Ok, mudei para InnerContextResource
Juan

1

Existem muitas maneiras de obter o contexto do aplicativo no aplicativo Spring. Esses são dados abaixo:

  1. Via 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;
    }
    }

Aqui setApplicationContext(ApplicationContext applicationContext)você obterá o método applicationContext

  1. Via Autowired :

    @Autowired
    private ApplicationContext applicationContext;

Aqui, a @Autowiredpalavra-chave fornecerá o applicationContext.

Para mais informações visite este tópico

Obrigado :)


0

Outra maneira é injetar applicationContext por meio do servlet.

Este é um exemplo de como injetar dependências ao usar serviços da web 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>

A maneira alternativa é adicionar o contexto do aplicativo em seu web.xml como mostrado abaixo

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

Basicamente, você está tentando dizer ao servlet que ele deve procurar por beans definidos nesses arquivos de contexto.


0

Etapa 1 : injetar o seguinte código na aula

@Autowired
private ApplicationContext _applicationContext;

Etapa 2 : Escreva Getter e Setter

Etapa 3 : defina autowire = "byType" no arquivo xml no qual o bean é definido


0

Mesmo depois de adicionar @Autowire se sua classe não for um RestController ou uma classe de configuração, o objeto applicationContext estava vindo como nulo. Tentei criar uma nova classe com a seguir e está funcionando bem:

@Component
public class SpringContext implements ApplicationContextAware{

   private static ApplicationContext applicationContext;

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

você pode, então, implementar um método getter na mesma classe de acordo com sua necessidade, como obter a referência de classe implementada por:

    applicationContext.getBean(String serviceName,Interface.Class)

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

Então você pode recuperar o bean:

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

Referência: springbyexample.org


25
Essa resposta não fornece o contexto atual ; em vez disso, cria outra instância.
Jaroslav Záruba
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.