Existe uma maneira de solicitar estaticamente / globalmente uma cópia do ApplicationContext em um aplicativo Spring?
Supondo que a classe principal seja inicializada e inicialize o contexto do aplicativo, ela deve ser transmitida através da pilha de chamadas para as classes que precisam, ou existe uma maneira de uma classe solicitar o contexto criado anteriormente? (Que eu assumo que deve ser um singleton?)
fonte
instance()
método do singleton como fábrica. No entanto, acho que deixei todo o código fora do contêiner acessar o contêiner primeiro. Então esse código pode solicitar objetos do contêiner.Você pode implementar
ApplicationContextAware
ou apenas usar@Autowired
:SpringBean
teráApplicationContext
injetado, dentro do qual esse bean é instanciado. Por exemplo, se você tiver um aplicativo da Web com uma hierarquia de contextos bastante padrão:e
SpringBean
é declarado no contexto principal, ele será injetado no contexto principal; caso contrário, se for declarado no contexto do MVC, ele será injetado no contexto do MVC.fonte
@Inject
tambémAqui está uma maneira agradável (não minha, a referência original está aqui: http://sujitpal.blogspot.com/2007/03/accessing-spring-beans-from-legacy-code.html
Eu usei essa abordagem e funciona bem. Basicamente, é um bean simples que contém uma referência (estática) ao contexto do aplicativo. Ao referenciá-lo na configuração da primavera, ele é inicializado.
Dê uma olhada na ref original, é muito claro.
fonte
getBean
do código executado durante um teste de unidade, porque o contexto do Spring não será configurado antes de você solicitá-lo. É uma condição de corrida que acabei de bater hoje após 2 anos de sucesso usando essa abordagem.Eu acredito que você poderia usar SingletonBeanFactoryLocator . O arquivo beanRefFactory.xml conteria o applicationContext real, seria algo assim:
E o código para obter um bean do aplicativo application de onde quer que seja algo como isto:
A equipe da Primavera desencoraja o uso dessa classe e do yadayada, mas me serviu bem onde eu a usei.
fonte
Antes de implementar qualquer uma das outras sugestões, faça estas perguntas a si mesmo ...
As respostas a essas perguntas são mais fáceis em certos tipos de aplicativos (aplicativos da Web, por exemplo) do que em outros, mas vale a pena perguntar de qualquer maneira.
O acesso ao ApplicationContext viola todo o princípio da injeção de dependência, mas às vezes você não tem muita escolha.
fonte
Se você usar um aplicativo da Web, também há outra maneira de acessar o contexto do aplicativo sem usar singletons usando um servletfilter e um ThreadLocal. No filtro, você pode acessar o contexto do aplicativo usando WebApplicationContextUtils e armazenar o contexto do aplicativo ou os beans necessários no TheadLocal.
Cuidado: se você esquecer de desabilitar o ThreadLocal, terá problemas desagradáveis ao tentar desimplementar o aplicativo! Portanto, você deve configurá-lo e iniciar imediatamente uma tentativa que desativa o ThreadLocal na parte final.
Obviamente, isso ainda usa um singleton: o ThreadLocal. Mas os grãos reais não precisam mais ser. Pode até ter um escopo de solicitação e essa solução também funcionará se você tiver vários WARs em um Aplicativo com as bibliotecas no EAR. Ainda assim, você pode considerar esse uso do ThreadLocal tão ruim quanto o uso de singletons simples. ;-)
Talvez o Spring já forneça uma solução semelhante? Não encontrei um, mas não tenho certeza.
fonte
Fonte: http://sujitpal.blogspot.de/2007/03/accessing-spring-beans-from-legacy-code.html
fonte
Dê uma olhada em ContextSingletonBeanFactoryLocator . Ele fornece acessadores estáticos para se apossar dos contextos do Spring, supondo que eles tenham sido registrados de determinadas maneiras.
Não é bonito e mais complexo do que você gostaria, mas funciona.
fonte
Existem várias maneiras de obter o contexto do aplicativo no aplicativo Spring. Estes são dados abaixo:
Via ApplicationContextAware :
Aqui
setApplicationContext(ApplicationContext applicationContext)
método, você receberá o applicationContextVia Autowired :
Aqui a
@Autowired
palavra-chave fornecerá o applicationContext. O fio automático tem algum problema. Isso criará problemas durante o teste de unidade.fonte
Observe que, armazenando qualquer estado da corrente
ApplicationContext
ou aApplicationContext
própria em uma variável estática - por exemplo, usando o padrão singleton - você tornará seus testes instáveis e imprevisíveis se estiver usando o Spring-test. Isso ocorre porque o teste Spring armazena em cache e reutiliza os contextos de aplicativos na mesma JVM. Por exemplo:@ContextConfiguration({"classpath:foo.xml"})
.@ContextConfiguration({"classpath:foo.xml", "classpath:bar.xml})
@ContextConfiguration({"classpath:foo.xml"})
Quando o Teste A é executado, um
ApplicationContext
é criado e qualquer bean queApplicationContextAware
implemente ou fiação automáticaApplicationContext
pode gravar na variável estática.Quando o Teste B é executado, acontece a mesma coisa, e a variável estática agora aponta para os Testes B
ApplicationContext
Quando o Teste C é executado, nenhum bean é criado quando o
TestContext
(e aqui oApplicationContext
) do Teste A é reutilizado. Agora você tem uma variável estática apontando para outraApplicationContext
que não a que está atualmente segurando o bean para o seu teste.fonte
Não sabe ao certo quão útil isso será, mas você também pode obter o contexto ao inicializar o aplicativo. Este é o mais rápido que você pode obter no contexto, mesmo antes de um
@Autowire
.fonte
Por favor note que; o código abaixo criará um novo contexto de aplicativo em vez de usar o já carregado.
Observe também que
beans.xml
deve fazer parte dossrc/main/resources
meios na guerra em que faz parteWEB_INF/classes
, onde a aplicação real será carregada através doapplicationContext.xml
mencionado emWeb.xml
.É difícil mencionar o
applicationContext.xml
caminho noClassPathXmlApplicationContext
construtor.ClassPathXmlApplicationContext("META-INF/spring/applicationContext.xml")
não conseguirá localizar o arquivo.Portanto, é melhor usar o applicationContext existente usando anotações.
fonte
Sei que esta pergunta foi respondida, mas gostaria de compartilhar o código Kotlin que fiz para recuperar o contexto da primavera.
Como não sou especialista, estou aberto a críticas, críticas e conselhos:
https://gist.github.com/edpichler/9e22309a86b97dbd4cb1ffe011aa69dd
Agora, um contexto de primavera está disponível publicamente, podendo chamar o mesmo método independentemente do contexto (testes de junit, beans, classes instanciadas manualmente) como neste Java Servlet:
fonte
Faça a conexão automática no Spring bean como abaixo: @Autowired private ApplicationContext appContext;
você será o objeto applicationcontext.
fonte
Abordagem 1: você pode injetar ApplicationContext implementando a interface ApplicationContextAware. Link de referência .
Abordagem 2: Contexto do aplicativo Autowire em qualquer um dos beans gerenciados por primavera.
Link de referência .
fonte