Spring mendapatkan ApplicationContext saat ini

105

Saya menggunakan Spring MVC untuk aplikasi web saya. Kacang saya ditulis dalam spring-servlet.xmlfile " "

Sekarang saya memiliki kelas MyClassdan saya ingin mengakses kelas ini menggunakan kacang musim semi

Di bawah spring-servlet.xmlsaya telah menulis

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

Sekarang saya perlu mengakses ini menggunakan ApplicationContext

ApplicationContext context = ??

Sehingga saya bisa melakukannya

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

Bagaimana cara melakukannya??

LynA
sumber
3
@Autowired MyClass myClass harus melakukan pekerjaan itu!
Mannekenpix

Jawaban:

161

Cukup suntik ..

@Autowired
private ApplicationContext appContext;

atau terapkan antarmuka ini: ApplicationContextAware

gipinani.dll
sumber
Mungkin ini bisa berhasil: stackoverflow.com/questions/11682858/…
gipinani
ApplicationContextProvider.javaJawaban berikut tampaknya menjadi solusi paling andal untuk ini.
Ionut
1
Itu mengembalikan NULL setiap saat. Untuk menyebutkan di sini bahwa saya melakukan ini di dalam kelas normal yang bukan "@RestController" atau "@Component"
shah
1
Menurut dokumentasi Spring, sebaiknya hindari @Autowired karena beberapa masalah. Ini adalah tautan spring.io/understanding/application-context . Pilihan terbaik adalah pergi dengan mengimplementasikan antarmuka ApplicationContextAware.
Durja Arai
89

Saya pikir tautan ini menunjukkan cara terbaik untuk mendapatkan konteks aplikasi di mana saja, bahkan di kelas non-kacang. Saya merasa sangat berguna. Semoga hal yang sama untuk Anda. Di bawah ini adalah kode abstraknya

Buat kelas baru 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;
    }
}

Tambahkan entri di application-context.xml

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

Dalam kasus anotasi (bukan application-context.xml)

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

Dapatkan konteksnya seperti ini

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

Bersulang!!

Vivek
sumber
1
Saya kode mirip dengan Vivek. Tetapi saya menghindari membuat ApplicationContextProvider () baru setiap kali saya perlu memanggil getBean () dari konteksnya. Apa yang saya lakukan adalah memiliki metode statis ApplicationContextProvider.getApplicationContext() . Kemudian, ketika saatnya membutuhkan konteks aplikasi saat ini, saya meminta:ApplicationContextProvider appContext = ApplicationContextProvider.getApplicationContext()
Panini Luncher
1
Ya Panini Luncher, itu masih bagus. Sesuai saran Anda, saya akan mengubahnya seperti itu. :)
Vivek
4
Add @Componenton ApplicationContextProviderdapat menghindari konfigurasi diaplication-context.xml
bluearrow
1
Catatan: pengambil dan penyetel konteks harus disinkronkan. Anda akan menghindari banyak sakit kepala khususnya untuk unit / tes integrasi. Dalam kasus saya ApplicationContextProvider serupa memegang konteks lama (dari uji integrasi sebelumnya) yang menyebabkan banyak bug rumit.
Oleksandr_DJ
43

Jika Anda perlu mengakses konteks dari dalam HttpServlet yang tidak dibuat oleh Spring (dan karenanya baik @Autowire maupun ApplicationContextAware tidak akan berfungsi) ...

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

atau

SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(this);

Adapun beberapa balasan lainnya, pikirkan dua kali sebelum Anda melakukan ini:

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

... karena ini tidak memberi Anda konteks saat ini, melainkan membuat contoh lain untuk Anda. Yang berarti 1) potongan memori yang signifikan dan 2) kacang tidak dibagikan di antara dua konteks aplikasi ini.

Jaroslav Záruba
sumber
SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext (this) - melakukan pekerjaan untuk saya dalam metode init () filter tindakan portlet Liferay.
Igor Baiborodine
Luar biasa, processInjectionBasedOnCurrentContext melakukan semua pekerjaan yang saya butuhkan. Terima kasih banyak @Jaroslav
Jad B.
ApplicationContextAware BERLAKU untuk saya, ketika dianotasi dengan @Component seperti dalam solusi Vivek (Saya menginisialisasi konteks Spring secara manual melalui perluasan AbstractContextLoaderInitializer / createRootApplicationContext)
hello_earth
Berhati-hatilah ... SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext (this); tidak segera terjadi, jadi Anda tidak dapat menggunakannya sebagai baris pertama dalam konstruktor Anda misalnya.
SledgeHammer
31

Jika Anda mengimplementasikan kelas yang tidak dibuat oleh Spring, seperti JsonDeserializer, Anda dapat menggunakan:

WebApplicationContext context = ContextLoader.getCurrentWebApplicationContext();
MyClass myBean = context.getBean(MyClass.class);
rzymek.dll
sumber
8
Itu tidak berhasil bagi saya. Kelas saya di luar konteks Musim Semi. Saya sudah mencoba menggunakan kode Anda tetapi memberi saya null sebagai tanggapan. Yang saya bicarakanContextLoader.getCurrentWebApplicationContext()
R. Karlus
9

Tambahkan ini ke kode Anda

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

Ini hanya akan menyuntikkan myClass ke dalam aplikasi Anda

Hitesh Kumar
sumber
6

berdasarkan jawaban Vivek, tapi menurut saya yang berikut akan lebih baik:

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

Menulis dari metode instance ke kolom statis adalah praktik yang buruk dan berbahaya jika beberapa instance sedang dimanipulasi.

Juan
sumber
Ada org.springframework.core.io.ContextResourceantarmuka. Saya menyarankan untuk memilih nama yang berbeda untuk kelas batin ContextResourcehanya untuk menghindari kekacauan.
Alexander Radchenko
@AlexanderRadchenko Oke, saya mengubahnya menjadi InnerContextResource
Juan
1

Ada banyak cara untuk mendapatkan konteks aplikasi dalam aplikasi Spring. Itu diberikan di bawah ini:

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

Di sini setApplicationContext(ApplicationContext applicationContext)metode Anda akan mendapatkan applicationContext

  1. Melalui Autowired :

    @Autowired
    private ApplicationContext applicationContext;

Di sini @Autowiredkata kunci akan memberikan applicationContext.

Untuk info lebih lanjut kunjungi utas ini

Terima kasih :)

Md. Sajedul Karim
sumber
0

Cara lain adalah dengan menginjeksi applicationContext melalui servlet.

Ini adalah contoh cara memasukkan dependensi saat menggunakan layanan 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>

Cara alternatif adalah dengan menambahkan Konteks aplikasi di web.xml Anda seperti yang ditunjukkan di bawah ini

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

Pada dasarnya Anda mencoba memberi tahu servlet bahwa ia harus mencari kacang yang didefinisikan dalam file konteks ini.

vsingh
sumber
0

Langkah 1 : Masukkan kode berikut di kelas

@Autowired
private ApplicationContext _applicationContext;

Langkah 2 : Tulis Getter & Setter

Langkah 3 : tentukan autowire = "byType" dalam file xml di mana bean didefinisikan

Kamlesh Paunikar
sumber
0

Bahkan setelah menambahkan @Autowire jika kelas Anda bukan RestController atau Kelas Konfigurasi, objek applicationContext tetap bernilai null. Mencoba Membuat kelas baru dengan di bawah ini dan berfungsi dengan baik:

@Component
public class SpringContext implements ApplicationContextAware{

   private static ApplicationContext applicationContext;

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

Anda kemudian dapat mengimplementasikan metode pengambil di kelas yang sama sesuai kebutuhan Anda seperti mendapatkan referensi kelas yang Diimplementasikan dengan:

    applicationContext.getBean(String serviceName,Interface.Class)
Aman Malhotra
sumber
-11
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("/spring-servlet.xml");

Kemudian Anda dapat mengambil kacang:

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

Referensi: springbyexample.org

PraZ
sumber
25
Jawaban ini tidak memberi Anda konteks saat ini , melainkan menciptakan contoh lain.
Jaroslav Záruba