Saya sedang belajar Spring 3 dan sepertinya saya tidak memahami fungsi di belakang <context:annotation-config>
dan <context:component-scan>
.
Dari apa yang saya baca mereka tampaknya untuk menangani berbagai penjelasan ( @Required
, @Autowired
dll vs @Component
, @Repository
, @Service
dll), tetapi juga dari apa yang saya baca mereka mendaftar sama prosesor posting kacang kelas.
Yang lebih membingungkan saya, ada annotation-config
atribut di <context:component-scan>
.
Adakah yang bisa menjelaskan tag ini? Apa yang mirip, apa yang berbeda, apakah yang satu digantikan oleh yang lain, mereka saling melengkapi, apakah saya memerlukan salah satunya, keduanya?
java
spring
configuration
annotations
spring-3
pengguna938214097
sumber
sumber
component-scan
kapan pun memungkinkan.Jawaban:
<context:annotation-config>
digunakan untuk mengaktifkan anotasi dalam kacang yang sudah terdaftar dalam konteks aplikasi (tidak peduli apakah itu didefinisikan dengan XML atau dengan pemindaian paket).<context:component-scan>
juga dapat melakukan apa yang<context:annotation-config>
dilakukan tetapi<context:component-scan>
juga memindai paket untuk menemukan dan mendaftarkan kacang dalam konteks aplikasi.Saya akan menggunakan beberapa contoh untuk menunjukkan perbedaan / kesamaan.
Mari kita mulai dengan pengaturan dasar tiga jenis kacang
A
,B
danC
, denganB
danC
disuntikkanA
.Dengan konfigurasi XML berikut:
Memuat konteks menghasilkan output berikut:
OK, ini adalah output yang diharapkan. Tapi ini adalah "gaya lama" Musim Semi. Sekarang kita memiliki anotasi jadi mari kita gunakan itu untuk menyederhanakan XML.
Pertama, mari kita autowire
bbb
danccc
properti pada kacangA
seperti:Ini memungkinkan saya untuk menghapus baris berikut dari XML:
XML saya sekarang disederhanakan menjadi ini:
Ketika saya memuat konteks saya mendapatkan output berikut:
OK, ini salah! Apa yang terjadi? Mengapa properti saya tidak disiarkan otomatis?
Ya, anotasi adalah fitur yang bagus tetapi dengan sendirinya mereka tidak melakukan apa pun. Mereka hanya membubuhi keterangan hal. Anda memerlukan alat pemrosesan untuk menemukan anotasi dan melakukan sesuatu dengannya.
<context:annotation-config>
untuk menyelamatkan. Ini mengaktifkan tindakan untuk anotasi yang ditemukan pada kacang yang didefinisikan dalam konteks aplikasi yang sama di mana itu sendiri didefinisikan.Jika saya mengubah XML saya ke ini:
ketika saya memuat konteks aplikasi saya mendapatkan hasil yang tepat:
OK, ini bagus, tapi saya sudah menghapus dua baris dari XML dan menambahkan satu. Itu bukan perbedaan yang sangat besar. Gagasan dengan anotasi adalah bahwa seharusnya menghapus XML.
Jadi mari kita hapus definisi XML dan ganti semuanya dengan anotasi:
Sementara di XML kami hanya menyimpan ini:
Kami memuat konteks dan hasilnya adalah ... Tidak ada. Tidak ada kacang yang dibuat, tidak ada kacang yang diotomatiskan. Tidak ada!
Itu karena, seperti yang saya katakan di paragraf pertama,
<context:annotation-config />
hanya bekerja pada kacang yang terdaftar dalam konteks aplikasi. Karena saya menghapus konfigurasi XML untuk tiga kacang tidak ada kacang dibuat dan<context:annotation-config />
tidak memiliki "target" untuk bekerja.Tapi itu tidak akan menjadi masalah
<context:component-scan>
yang dapat memindai paket untuk "target" untuk dikerjakan. Mari kita ubah konten konfigurasi XML menjadi entri berikut:Ketika saya memuat konteks saya mendapatkan output berikut:
Hmmmm ... ada yang hilang. Mengapa?
Jika Anda melihat tertutup di kelas, kelas
A
memiliki paketcom.yyy
tetapi saya telah menentukan dalam<context:component-scan>
paket menggunakancom.xxx
sehingga ini benar-benar merindukanA
kelas saya dan hanya mengambilB
danC
yang ada dicom.xxx
paket.Untuk memperbaikinya, saya menambahkan paket lain ini juga:
dan sekarang kami mendapatkan hasil yang diharapkan:
Dan itu dia! Sekarang Anda tidak memiliki definisi XML lagi, Anda memiliki anotasi.
Sebagai contoh terakhir, menjaga kelas beranotasi
A
,B
danC
dan menambahkan yang berikut ke XML, apa yang akan kita dapatkan setelah memuat konteks?Kami masih mendapatkan hasil yang benar:
Bahkan jika kacang untuk kelas
A
tidak diperoleh dengan pemindaian, alat pemrosesan masih diterapkan oleh<context:component-scan>
semua kacang yang terdaftar dalam konteks aplikasi, bahkanA
yang kacang itu secara manual terdaftar dalam XML.Tetapi bagaimana jika kita memiliki XML berikut, apakah kita akan mendapatkan duplikat kacang karena kita telah menentukan keduanya
<context:annotation-config />
dan<context:component-scan>
?Tidak, tidak ada duplikasi, Kami kembali mendapatkan hasil yang diharapkan:
Itu karena kedua tag mendaftarkan alat pemrosesan yang sama (
<context:annotation-config />
dapat dihilangkan jika<context:component-scan>
ditentukan) tetapi Spring hanya menjalankannya sekali.Bahkan jika Anda mendaftarkan alat pemrosesan sendiri beberapa kali, Spring masih akan memastikan mereka melakukan sihir mereka hanya sekali; XML ini:
akan tetap menghasilkan hasil sebagai berikut:
OK, itu tentang mengetuknya.
Saya harap informasi ini bersama dengan tanggapan dari @Tomasz Nurkiewicz dan @Sean Patrick Floyd adalah semua yang Anda butuhkan untuk memahami bagaimana
<context:annotation-config>
dan<context:component-scan>
bekerja.sumber
Saya menemukan ringkasan bagus ini yang mana anotasi diambil oleh deklarasi mana. Dengan mempelajarinya Anda akan menemukan bahwa
<context:component-scan/>
superset dari anotasi diakui oleh<context:annotation-config/>
, yaitu:@Component
,@Service
,@Repository
,@Controller
,@Endpoint
@Configuration
,@Bean
,@Lazy
,@Scope
,@Order
,@Primary
,@Profile
,@DependsOn
,@Import
,@ImportResource
Seperti yang Anda lihat
<context:component-scan/>
secara logis diperluas<context:annotation-config/>
dengan pemindaian komponen CLASSPATH dan fitur Java @Configuration.sumber
Spring memungkinkan Anda melakukan dua hal:
1. Autowiring
Biasanya dalam applicationContext.xml Anda mendefinisikan kacang dan kacang lainnya ditransfer menggunakan metode konstruktor atau penyetel. Anda bisa mengirim kacang menggunakan XML atau anotasi. Jika Anda menggunakan anotasi, Anda harus mengaktifkan anotasi dan Anda harus menambahkan
<context:annotation-config />
di applicationContext.xml . Ini akan menyederhanakan struktur tag dari applicationContext.xml , karena Anda tidak harus secara manual memasang kacang (konstruktor atau setter). Anda dapat menggunakan@Autowire
anotasi dan kacang akan ditransfer berdasarkan jenis.Langkah maju untuk keluar dari konfigurasi XML manual adalah
2. Autodiscovery
Autodiscovery menyederhanakan XML satu langkah lebih jauh, dalam arti Anda bahkan tidak perlu menambahkan
<bean>
tag di applicationContext.xml . Anda cukup menandai kacang spesifik dengan salah satu anotasi berikut dan Pegas akan secara otomatis memasukkan kacang yang ditandai dan ketergantungannya ke wadah Pegas. Anotasi adalah sebagai berikut: @Controller , @Service , @Component , @Repository . Dengan menggunakan<context:component-scan>
dan mengarahkan paket dasar, Spring akan menemukan secara otomatis dan mengirimkan komponen ke wadah Spring.Sebagai sebuah kesimpulan:
<context:annotation-config />
digunakan agar dapat menggunakan anotasi @Autowired<context:component-scan />
digunakan untuk menentukan pencarian kacang spesifik dan upaya autowiring.sumber
<context:annotation-config>
mengaktifkan banyak anotasi berbeda dalam buncis, baik didefinisikan dalam XML atau melalui pemindaian komponen.<context:component-scan>
adalah untuk mendefinisikan kacang tanpa menggunakan XMLUntuk informasi lebih lanjut, baca:
sumber
<context:component-scan>
saya tidak akan bisa menimpa definisi kacang menggunakan XML?<context:component-scan>
? Apakah saya kehilangan sesuatu jika saya tidak menggunakannya<context:annotation-config>
?Perbedaan antara keduanya sangat sederhana !.
Memungkinkan Anda untuk menggunakan anotasi yang dibatasi hanya untuk mengabel properti dan konstruktor kacang !.
Dimana sebagai
Memungkinkan segala sesuatu yang
<context:annotation-config />
dapat Anda lakukan, dengan penambahan menggunakan stereotip misalnya ..@Component
,@Service
,@Repository
. Jadi, Anda dapat mentransfer seluruh kacang dan tidak hanya terbatas pada konstruktor atau properti !.sumber
<context:annotation-config>
: Memindai dan mengaktifkan anotasi untuk kacang yang sudah terdaftar di konfigurasi musim semi xml.<context:component-scan>
: Registrasi kacang +<context:annotation-config>
@Autowired dan @Required adalah target level properti sehingga bean harus mendaftar di IOC musim semi sebelum menggunakan anotasi ini. Untuk mengaktifkan anotasi ini, Anda harus mendaftarkan kacang masing-masing atau memasukkannya
<context:annotation-config />
. yaitu hanya<context:annotation-config />
bekerja dengan kacang terdaftar.@Required mengaktifkan
RequiredAnnotationBeanPostProcessor
alat pemrosesan@Autowired memungkinkan
AutowiredAnnotationBeanPostProcessor
alat pemrosesanCatatan: Anotasi itu sendiri tidak ada hubungannya, kita memerlukan Alat Pemrosesan , yang merupakan kelas di bawahnya, yang bertanggung jawab untuk proses inti.
@Repository, @Service dan @Controller adalah @Component , dan mereka menargetkan level kelas .
<context:component-scan>
itu memindai paket dan menemukan dan mendaftarkan kacang, dan itu termasuk pekerjaan yang dilakukan oleh<context:annotation-config />
.Memigrasi XML ke Anotasi
sumber
The
<context:annotation-config>
tag memberitahu Spring ke memindai basis kode untuk secara otomatis menyelesaikan persyaratan ketergantungan dari kelas yang mengandung penjelasan @ Autowired.Spring 2.5 juga menambahkan dukungan untuk anotasi JSR-250 seperti @Resource, @PostConstruct, dan @ PreDestroy. Penggunaan anotasi ini juga mengharuskan BeanPostProcessors tertentu didaftarkan dalam wadah Spring. Seperti biasa, ini dapat didaftarkan sebagai definisi kacang individu, tetapi mereka juga dapat didaftarkan secara implisit dengan memasukkan
<context:annotation-config>
tag dalam konfigurasi pegas.Diambil dari dokumentasi Spring dari Annotation Based Configuration
Spring menyediakan kemampuan mendeteksi kelas 'stereotip' secara otomatis dan mendaftarkan BeanDefinitions yang sesuai dengan ApplicationContext.
Menurut javadoc dari org.springframework.stereotype :
Stereotip adalah Anotasi yang menunjukkan peran tipe atau metode dalam arsitektur keseluruhan (pada level konseptual, bukan implementasi,). Contoh: @Controller @Service @Repository, dll. Ini dimaksudkan untuk digunakan oleh alat dan aspek (membuat target ideal untuk pointcuts).
Untuk mendeteksi secara otomatis kelas 'stereotip' semacam itu,
<context:component-scan>
tag diperlukan.The
<context:component-scan>
tag juga mengatakan musim semi untuk memindai kode untuk kacang suntik di bawah paket (dan semua subpackages nya) ditentukan.sumber
Hanya menyelesaikan
@Autowired
dan@Qualifer
anotasi, itu saja, tentang Injeksi Ketergantungan , Ada anotasi lain yang melakukan pekerjaan yang sama, saya pikir caranya@Inject
, tetapi semua akan menyelesaikan DI melalui anotasi.Sadarilah, bahkan ketika Anda telah mendeklarasikan
<context:annotation-config>
elemen, Anda harus mendeklarasikan kelas Anda bagaimana sebuah Bean, ingat kami memiliki tiga opsi yang tersedia<bean>
Sekarang dengan
Ia melakukan dua hal:
<context:annotation-config>
.Karena itu jika Anda mendeklarasikan
<context:component-scan>
, tidak perlu lagi mendeklarasikan<context:annotation-config>
juga.Itu saja
Skenario yang umum misalnya menyatakan hanya kacang melalui XML dan menyelesaikan DI melalui penjelasan, misalnya
Kami hanya menyatakan kacang, tidak ada tentang
<constructor-arg>
dan<property>
, DI dikonfigurasi di kelas mereka sendiri melalui @ Autowired. Ini berarti Layanan menggunakan @ Autowired untuk komponen Repositori mereka dan Repositori menggunakan @ Autowired untuk JdbcTemplate, DataSource dll. Komponensumber
coba dengan
<context:component-scan base-package="..." annotation-config="false"/>
, di konfigurasi @Service, @Repository, @Component berfungsi dengan baik, tetapi @ Autowired, @ Resource dan @Inject tidak berfungsi.Ini berarti AutowiredAnnotationBeanPostProcessor tidak akan diaktifkan dan Spring container tidak akan memproses anotasi Autowiring.
sumber
Poin penting lainnya yang perlu diperhatikan adalah bahwa
context:component-scan
panggilan secara implisitcontext:annotation-config
untuk mengaktifkan anotasi pada kacang. Nah, jika Anda tidak ingincontext:component-scan
secara aktif mengaktifkan anotasi untuk Anda, Anda dapat mengatur elemen anotasi-konfigurasi daricontext:component-scan
tofalse
.Untuk meringkas:
sumber
<context:component-scan base-package="package name" />
:Ini digunakan untuk memberi tahu kontainer bahwa ada kelas-kelas kacang dalam paket saya, memindai kelas-kelas kacang itu. Untuk memindai kelas kacang dengan wadah di atas kacang, kita harus menulis salah satu anotasi jenis stereo seperti berikut.
@Component
,@Service
,@Repository
,@Controller
<context:annotation-config />
:Jika kita tidak ingin menulis tag kacang secara eksplisit dalam XML maka bagaimana wadah tahu jika ada kabel otomatis di kacang. Ini dimungkinkan dengan menggunakan
@Autowired
anotasi. kita harus memberi tahu kontainer bahwa ada kabel otomatis di dalam kacangkucontext:annotation-config
.sumber
Sebuah
<context:component-scan/>
tag kustom register set yang sama definisi kacang seperti yang dilakukan oleh, selain dari tanggung jawab utamanya pemindaian paket java dan mendaftarkan definisi kacang dari classpath.Jika karena alasan tertentu registrasi definisi kacang default ini harus dihindari, cara untuk melakukannya adalah menentukan atribut "annotation-config" tambahan dalam pemindaian komponen, dengan cara ini:
Referensi: http://www.java-allandsundry.com/2012/12/contextcomponent-scan-contextannotation.html
sumber
<context:annotation-config>
:Ini memberitahu Spring bahwa saya akan menggunakan kacang beranotasi sebagai kacang pegas dan yang akan ditransfer melalui
@Autowired
penjelasan, daripada mendeklarasikan dalam file xml konfigurasi musim semi.<context:component-scan base-package="com.test...">
:Ini memberitahu wadah Spring, di mana untuk mulai mencari kacang beranotasi. Di sini pegas akan mencari semua sub paket dari paket dasar.
sumber
Anda dapat menemukan informasi lebih lanjut dalam file skema konteks musim semi. berikut ini dalam konteks-musim semi-4.3.xsd
sumber
Sebagai pelengkap, Anda dapat menggunakan
@ComponentScan
untuk digunakan<context:component-scan>
dalam cara anotasi.Ini juga dijelaskan di spring.io
Satu hal yang perlu diperhatikan, jika Anda menggunakan Spring Boot, @Configuration dan @ComponentScan dapat diimplikasikan dengan menggunakan anotasi @SpringBootApplication.
sumber