Bahar mevcut ApplicationContext'i edinin


105

Web uygulamam için Spring MVC kullanıyorum. Fasulyelerim " spring-servlet.xml" dosyasına yazılıyor

Şimdi bir sınıfım var MyClassve bu sınıfa bahar fasulyesi kullanarak erişmek istiyorum

In spring-servlet.xmli yazdım aşağıda

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

Şimdi buna erişmem gerekiyor ApplicationContext

ApplicationContext context = ??

Böylece yapabilirim

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

Bu nasıl yapılır??


3
@Autowired MyClass myClass işi yapmalı!
Mannekenpix

Yanıtlar:


161

Sadece enjekte edin ..

@Autowired
private ApplicationContext appContext;

veya şu arabirimi uygulayın: ApplicationContextAware



Aşağıdaki ApplicationContextProvider.javacevap, bunun için en güvenilir çözüm gibi görünüyor.
Ionut

1
Her seferinde NULL döndürüyor. Burada bunu ne "@RestController" ne de "@Component" olmayan normal bir sınıfta yaptığımı belirtmek gerekirse
zulkarnain shah

1
Bahar belgelerine göre, bazı sorunlar nedeniyle @Autowired'dan kaçınmak en iyisidir. İşte spring.io/understanding/application-context bağlantısı . En iyi seçenek, ApplicationContextAware arayüzünü uygulamaktır.
Durja Arai

89

Bu bağlantının , bean olmayan sınıfta bile her yerde uygulama bağlamını almanın en iyi yolunu gösterdiğini düşünüyorum . Bunu çok faydalı buluyorum. Umarım sizin için aynıdır. Aşağıdaki soyut koddur

Yeni bir sınıf ApplicationContextProvider.java oluşturun

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 dosyasına bir girdi ekleyin

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

Ek açıklamalar durumunda (application-context.xml yerine)

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

Bunun gibi bağlamı alın

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

Şerefe !!


1
Vivek'e benzer şekilde kodladım. Ancak bağlamdan getBean () 'i çağırmam gerektiği her seferinde yeni ApplicationContextProvider () oluşturmaktan kaçınıyorum. Yaptığım şey statik ApplicationContextProvider.getApplicationContext() metoda sahip olmaktı . Ardından, mevcut uygulama bağlamına ihtiyaç duyma zamanı geldiğinde şunu ApplicationContextProvider appContext = ApplicationContextProvider.getApplicationContext()
çağırırım

1
Evet Panini Luncher, bu yine de iyi olur. Önerinize göre onu bu şekilde değiştireceğim. :)
Vivek

4
Eklenti @Component, ApplicationContextProvideryapılandırmayı önleyebiliraplication-context.xml
bluearrow

1
Not: Alıcı ve bağlam belirleyici senkronize edilmelidir. Özellikle ünite / entegrasyon testleri için çok fazla baş ağrısından kaçınacaksınız. Benim durumumda, benzer ApplicationContextProvider, birçok zor hataya neden olan eski bağlamı (önceki entegrasyon testinden) tuttu.
Oleksandr_DJ

43

İçeriğe Spring tarafından somutlaştırılmayan bir HttpServlet içinden erişmeniz gerektiğinde (ve bu nedenle ne @Autowire ne de ApplicationContextAware çalışmayacaktır) ...

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

veya

SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(this);

Diğer bazı yanıtlara gelince, bunu yapmadan önce iki kez düşünün:

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

... bu size mevcut bağlamı vermediği için sizin için başka bir örneğini yaratır. Bu, 1) önemli miktarda bellek ve 2) çekirdeklerin bu iki uygulama bağlamı arasında paylaşılmadığı anlamına gelir.


SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext (bu) - Liferay portlet eylem filtresinin init () yönteminde işi benim için yaptı.
Igor Baiborodine

Harika, processInjectionBasedOnCurrentContext ihtiyacım olan tüm işi yaptı. Çok teşekkürler @Jaroslav
Jad B.

ApplicationContextAware, Vivek'in çözümünde olduğu gibi @Component ile açıklama eklendiğinde (AbstractContextLoaderInitializer / createRootApplicationContext'i genişleterek Spring bağlamını manuel olarak
başlatıyorum

Dikkat edin ... SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext (this); hemen gerçekleşmez, bu nedenle örneğin kurucunuzda ilk satır olarak kullanamazsınız.
SledgeHammer

31

Bir JsonDeserializer gibi Spring tarafından başlatılmamış bir sınıf uyguluyorsanız, şunları kullanabilirsiniz:

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

8
Benim için çalışmıyor. Sınıfım Bahar bağlamının dışında. Kodunuzu kullanmayı denedim ama bu bana yanıt olarak boş bir değer verdi. ContextLoader.getCurrentWebApplicationContext()
Şundan

9

Bunu kodunuza ekleyin

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

Bu, basitçe myClass'ı uygulamanıza enjekte edecektir.


6

Vivek'in cevabına dayanarak, ancak aşağıdakilerin daha iyi olacağını düşünüyorum:

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

Bir örnek yönteminden bir statik alana yazmak kötü bir uygulamadır ve birden fazla örnek değiştiriliyorsa tehlikelidir.


Orada org.springframework.core.io.ContextResourcearayüzü. ContextResourceDağınıklığı önlemek için iç sınıf için farklı bir isim seçmenizi öneririm .
Alexander Radchenko

@AlexanderRadchenko Tamam, bunu InnerContextResource olarak değiştirdim
Juan

1

Spring uygulamasında uygulama bağlamını almanın birçok yolu vardır. Bunlar aşağıda verilmiştir:

  1. ApplicationContextAware aracılığıyla :

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

Burada setApplicationContext(ApplicationContext applicationContext)yöntem applicationContext'i alacaksınız

  1. Otomatik Kablolama ile :

    @Autowired
    private ApplicationContext applicationContext;

Burada @Autowiredanahtar kelime applicationContext'i sağlayacaktır.

Daha fazla bilgi için bu konuyu ziyaret edin

Teşekkürler :)


0

Başka bir yol applicationContext'i sunucu uygulaması aracılığıyla enjekte etmektir.

Bu, Spring web hizmetlerini kullanırken bağımlılıkların nasıl enjekte edileceğine bir örnektir.

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

Alternatif bir yol, aşağıda gösterildiği gibi web.xml dosyanıza uygulama Bağlamı eklemektir.

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

Temel olarak, servlet'e bu bağlam dosyalarında tanımlanan çekirdekleri araması gerektiğini söylemeye çalışıyorsunuz.


0

Adım 1 : Aşağıdaki kodu sınıfta enjekte edin

@Autowired
private ApplicationContext _applicationContext;

Adım 2 : Alıcı ve Ayarlayıcıyı Yazın

Adım 3 : bean'in tanımlandığı xml dosyasında autowire = "byType" ı tanımlayın


0

@Autowire ekledikten sonra bile sınıfınız bir RestController veya Yapılandırma Sınıfı değilse, applicationContext nesnesi null olarak geliyordu. Aşağıdakilerle yeni sınıf oluşturmayı denedim ve iyi çalışıyor:

@Component
public class SpringContext implements ApplicationContextAware{

   private static ApplicationContext applicationContext;

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

Daha sonra, Implemented sınıf referansını şu şekilde almak gibi, ihtiyacınıza göre aynı sınıfta bir getter yöntemi uygulayabilirsiniz:

    applicationContext.getBean(String serviceName,Interface.Class)

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

Sonra fasulyeyi alabilirsiniz:

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

Referans: springbyexample.org


25
Bu cevap size mevcut bağlamı vermez , daha çok başka bir örnek oluşturur.
Jaroslav Záruba
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.