Apakah ada cara untuk secara statis / global meminta salinan ApplicationContext dalam aplikasi Spring?
Dengan asumsi kelas utama memulai dan menginisialisasi konteks aplikasi, apakah itu perlu meneruskannya melalui tumpukan panggilan ke kelas yang membutuhkannya, atau adakah cara bagi kelas untuk meminta konteks yang dibuat sebelumnya? (Yang saya anggap harus singleton?)
java
spring
configuration
Joe Skora
sumber
sumber
instance()
sebagai pabrik. Namun, saya pikir saya hanya membiarkan semua kode di luar wadah mengakses wadah terlebih dahulu. Kemudian kode itu dapat meminta objek dari wadah.Anda dapat menerapkan
ApplicationContextAware
atau hanya menggunakan@Autowired
:SpringBean
akanApplicationContext
disuntikkan, di mana kacang ini dipakai. Misalnya jika Anda memiliki aplikasi web dengan hierarki konteks standar yang cantik:dan
SpringBean
dinyatakan dalam konteks utama, konteks utama akan disuntikkan; jika tidak, jika dinyatakan dalam konteks MVC, konteks MVC akan disuntikkan.sumber
@Inject
jugaIni cara yang bagus (bukan milik saya, referensi aslinya ada di sini: http://sujitpal.blogspot.com/2007/03/accessing-spring-beans-from-legacy-code.html
Saya telah menggunakan pendekatan ini dan berfungsi dengan baik. Pada dasarnya ini adalah kacang sederhana yang menyimpan referensi (statis) untuk konteks aplikasi. Dengan merujuknya pada konfigurasi pegas, itu diinisialisasi.
Lihatlah referensi asli, sangat jelas.
sumber
getBean
dari kode yang berjalan selama tes Unit karena konteks Spring tidak akan diatur sebelum Anda memintanya. Ini adalah kondisi balapan yang baru saja saya alami hari ini setelah 2 tahun berhasil menggunakan pendekatan ini.Saya yakin Anda bisa menggunakan SingletonBeanFactoryLocator . File beanRefFactory.xml akan menampung applicationContext yang sebenarnya, akan seperti ini:
Dan kode untuk mendapatkan kacang dari konteks aplikasi dari mana pun akan menjadi seperti ini:
Tim Spring mencegah penggunaan kelas ini dan yadayada, tapi itu sangat cocok untukku di tempat aku menggunakannya.
sumber
Sebelum Anda menerapkan saran lainnya, tanyakan pada diri sendiri pertanyaan-pertanyaan ini ...
Jawaban atas pertanyaan-pertanyaan ini lebih mudah di beberapa jenis aplikasi (aplikasi Web, misalnya) daripada yang lain, tetapi tetap layak ditanyakan.
Mengakses ApplicationContext memang melanggar prinsip injeksi dependensi secara keseluruhan, tetapi terkadang Anda tidak punya banyak pilihan.
sumber
Jika Anda menggunakan aplikasi web, ada juga cara lain untuk mengakses konteks aplikasi tanpa menggunakan lajang dengan menggunakan servletfilter dan ThreadLocal. Dalam filter Anda dapat mengakses konteks aplikasi menggunakan WebApplicationContextUtils dan menyimpan konteks aplikasi atau kacang yang diperlukan di TheadLocal.
Perhatian: jika Anda lupa untuk membatalkan ThreadLocal Anda akan mendapatkan masalah buruk ketika mencoba untuk tidak menggunakan aplikasi! Dengan demikian, Anda harus mengaturnya dan segera memulai percobaan yang membatalkan pengaturan ThreadLocal di bagian terakhir.
Tentu saja, ini masih menggunakan singleton: the ThreadLocal. Tetapi kacang yang sebenarnya tidak perlu lagi. Bahkan dapat dibatasi permintaan, dan solusi ini juga berfungsi jika Anda memiliki beberapa PERANG dalam Aplikasi dengan perpustakaan di EAR. Namun, Anda mungkin menganggap penggunaan ThreadLocal ini seburuk penggunaan lajang biasa. ;-)
Mungkin Spring sudah memberikan solusi serupa? Saya tidak menemukan satu, tetapi saya tidak tahu pasti.
sumber
Sumber: http://sujitpal.blogspot.de/2007/03/accessing-spring-beans-from-legacy-code.html
sumber
Lihatlah ContextSingletonBeanFactoryLocator . Ini menyediakan accessors statis untuk memahami konteks Spring, dengan asumsi mereka telah terdaftar dengan cara tertentu.
Ini tidak cantik, dan lebih kompleks dari yang Anda inginkan, tetapi berhasil.
sumber
Ada banyak cara untuk mendapatkan konteks aplikasi dalam aplikasi Spring. Itu diberikan di bawah ini:
Melalui ApplicationContextAware :
Di sini
setApplicationContext(ApplicationContext applicationContext)
metode Anda akan mendapatkan applicationContextMelalui Autowired :
Di sini
@Autowired
kata kunci akan memberikan konteks aplikasi. Autowired memiliki beberapa masalah. Ini akan menciptakan masalah selama pengujian unit.sumber
Perhatikan bahwa dengan menyimpan keadaan apa pun dari arus
ApplicationContext
, atauApplicationContext
dirinya sendiri dalam variabel statis - misalnya menggunakan pola tunggal - Anda akan membuat tes Anda tidak stabil dan tidak dapat diprediksi jika Anda menggunakan uji Spring. Ini karena uji Spring cache dan menggunakan kembali konteks aplikasi dalam JVM yang sama. Sebagai contoh:@ContextConfiguration({"classpath:foo.xml"})
.@ContextConfiguration({"classpath:foo.xml", "classpath:bar.xml})
@ContextConfiguration({"classpath:foo.xml"})
Ketika Uji A berjalan, sebuah
ApplicationContext
dibuat, dan kacang apa pun yang menerapkanApplicationContextAware
atau autiringiringApplicationContext
mungkin menulis ke variabel statis.Ketika Uji B menjalankan hal yang sama terjadi, dan variabel statis sekarang menunjuk ke Uji B
ApplicationContext
Saat Uji C berjalan, tidak ada kacang yang dibuat sebagai
TestContext
(dan di siniApplicationContext
) dari Uji A yang digunakan kembali. Sekarang Anda punya variabel statis yang menunjuk ke yang lainApplicationContext
dari yang saat ini memegang kacang untuk pengujian Anda.sumber
Tidak yakin seberapa berguna ini, tetapi Anda juga bisa mendapatkan konteks ketika Anda menginisialisasi aplikasi. Ini adalah yang tercepat Anda bisa mendapatkan konteksnya, bahkan sebelum
@Autowire
.sumber
Harap dicatat bahwa; kode di bawah ini akan membuat konteks aplikasi baru alih-alih menggunakan yang sudah dimuat.
Juga perhatikan bahwa
beans.xml
harus menjadi bagian darisrc/main/resources
sarana dalam perang itu adalah bagian dariWEB_INF/classes
, di mana aplikasi yang sebenarnya akan dimuat melaluiapplicationContext.xml
disebutkan diWeb.xml
.Hal ini sulit untuk menyebutkan
applicationContext.xml
jalan diClassPathXmlApplicationContext
konstruktor.ClassPathXmlApplicationContext("META-INF/spring/applicationContext.xml")
tidak dapat menemukan file.Jadi lebih baik menggunakan applicationContext yang sudah ada dengan menggunakan anotasi.
sumber
Saya tahu pertanyaan ini dijawab, tetapi saya ingin membagikan kode Kotlin yang saya lakukan untuk mengambil Konteks Musim Semi.
Saya bukan spesialis, jadi saya terbuka untuk kritik, ulasan, dan saran:
https://gist.github.com/edpichler/9e22309a86b97dbd4cb1ffe011aa69dd
Sekarang, konteks pegas tersedia untuk umum, dapat memanggil metode yang sama terlepas dari konteks (tes junit, kacang-kacangan, kelas yang dipakai secara manual) seperti pada Java Servlet ini:
sumber
Lakukan autowire dalam Spring bean seperti di bawah ini: @Autowired ApplicationContext private appContext;
Anda akan objek aplikasi konteks.
sumber
Pendekatan 1: Anda dapat menyuntikkan ApplicationContext dengan mengimplementasikan antarmuka ApplicationContextAware. Tautan referensi .
Pendekatan 2: Konteks Aplikasi Autowire di sembarang biji yang dikelola pegas
Tautan referensi .
sumber