Bagaimana cara memindai beberapa jalur menggunakan anotasi @ComponentScan?

90

Saya menggunakan Spring 3.1 dan melakukan bootstrap aplikasi menggunakan atribut @Configurationand @ComponentScan.

Awal yang sebenarnya dilakukan dengan

new AnnotationConfigApplicationContext(MyRootConfigurationClass.class);

Kelas Konfigurasi ini dianotasi dengan

@Configuration
@ComponentScan("com.my.package")
public class MyRootConfigurationClass

dan ini berfungsi dengan baik. Namun saya ingin lebih spesifik tentang paket yang saya pindai, jadi saya mencoba.

@Configuration
@ComponentScan("com.my.package.first,com.my.package.second")
public class MyRootConfigurationClass

Namun ini gagal dengan kesalahan yang memberi tahu saya bahwa tidak dapat menemukan komponen yang ditentukan menggunakan @Componentanotasi.

Apa cara yang benar untuk melakukan apa yang saya cari?

Terima kasih

Orang Pemrograman
sumber
Sejauh yang saya tahu, dua jawaban benar diberikan pada waktu yang sama. Aku akan menerima hage hanya karena dia memiliki poin lebih sedikit, tapi terima kasih keduanya.
Pemrogram
Jika Anda bertanya-tanya hal yang sama untuk versi kotlin, periksa stackoverflow.com/a/62818187/7747942 ini
Sylhare

Jawaban:

161

@ComponentScan menggunakan string array, seperti ini:

@ComponentScan({"com.my.package.first","com.my.package.second"})

Saat Anda memberikan beberapa nama paket hanya dalam satu string, Spring menafsirkan ini sebagai satu nama paket, dan karenanya tidak dapat menemukannya.

hage
sumber
48

Ada alternatif lain yang aman bagi tipe untuk menentukan lokasi paket dasar sebagai String. Lihat API di sini , tetapi saya juga mengilustrasikan di bawah ini:

@ComponentScan(basePackageClasses = {ExampleController.class, ExampleModel.class, ExmapleView.class})

Menggunakan penentu basePackageClasses dengan referensi kelas Anda akan memberi tahu Spring untuk memindai paket tersebut (seperti alternatif yang disebutkan ), tetapi metode ini aman untuk tipe dan menambahkan dukungan IDE untuk refactoring di masa mendatang - nilai tambah yang sangat besar dalam buku saya.

Membaca dari API, Spring menyarankan untuk membuat kelas atau antarmuka penanda tanpa operasi di setiap paket yang ingin Anda pindai yang tidak memiliki tujuan lain selain digunakan sebagai referensi untuk / oleh atribut ini.

IMO, saya tidak suka kelas-penanda (tetapi sekali lagi, mereka cukup mirip dengan kelas info paket) tetapi jenis keamanan, dukungan IDE, dan secara drastis mengurangi jumlah paket dasar yang diperlukan untuk disertakan untuk pemindaian ini adalah, tanpa keraguan, pilihan yang jauh lebih baik.

Prancer
sumber
Bisakah seseorang menjelaskan mengapa @ComponentScan ({"com.app", "com.controllers"}) tidak berfungsi untuk saya, tetapi @ComponentScan (basePackageClasses = {"com.controllers"}) berfungsi dengan baik? Saya merasa membosankan menulis setiap nama kelas
xaverras
3
Anda hanya perlu menentukan satu kelas dalam paket tersebut, untuk paket yang ingin Anda pindai. Ini dikenal sebagai kelas penanda. Jika Anda perlu memindai paket yang lebih tinggi dalam hierarki yang tidak memiliki kelas, spring menyarankan teknik yang menggunakan antarmuka "penanda pegas" atau kelas akhir yang ditentukan dalam paket itu semata-mata untuk tujuan pemindaian paket.
Prancer
17

Berikan nama paket Anda secara terpisah, ini membutuhkan String[]untuk nama paket.

Daripada ini:

@ComponentScan("com.my.package.first,com.my.package.second")

Gunakan ini:

@ComponentScan({"com.my.package.first","com.my.package.second"})
mprabhat
sumber
10

Cara lain untuk melakukan ini adalah dengan menggunakan basePackageslapangan; yang merupakan bidang di dalam anotasi ComponentScan.

@ComponentScan(basePackages={"com.firstpackage","com.secondpackage"})

Jika Anda melihat anotasi .class ComponentScan dari file jar, Anda akan melihat bidang basePackages yang memuat array Strings

public @interface ComponentScan {
String[] basePackages() default {};
}

Atau Anda bisa menyebutkan kelas secara eksplisit. Yang mengambil berbagai kelas

Class<?>[]  basePackageClasses
shashwatZing
sumber
4

Anda menggunakan ComponentScan untuk memindai beberapa paket menggunakan

@ComponentScan({"com.my.package.first","com.my.package.second"})

ksw
sumber
1

pastikan Anda telah menambahkan ketergantungan ini di pom.xml Anda

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
Amirtha Krishnan
sumber
Terima kasih setelah menghabiskan hampir setengah jam, ini adalah ketergantungan yang hilang
DvixExtract
1

Anda juga dapat menggunakan anotasi @ComponentScans:

@ComponentScans(value = { @ComponentScan("com.my.package.first"),
                          @ComponentScan("com.my.package.second") })
Farouk.ch
sumber
4
Silakan pertimbangkan untuk menambahkan penjelasan ke jawaban Anda
yeya
1

Saya menggunakan:

@ComponentScan(basePackages = {"com.package1","com.package2","com.package3", "com.packagen"})
Yann
sumber