Apa cara terbaik mencari seluruh kelas untuk kelas beranotasi?
Saya sedang melakukan perpustakaan dan saya ingin memungkinkan pengguna untuk membubuhi keterangan kelas mereka, jadi ketika aplikasi Web dimulai saya perlu memindai seluruh classpath untuk anotasi tertentu.
Apakah Anda tahu perpustakaan atau fasilitas Java untuk melakukan ini?
Sunting: Saya sedang memikirkan sesuatu seperti fungsi baru untuk Layanan Web Java EE 5 atau EJB. Anda membubuhi keterangan kelas Anda dengan @WebService
atau @EJB
dan sistem menemukan kelas-kelas ini saat memuat sehingga mereka dapat diakses dari jarak jauh.
sumber
@Conditional
anotasi. Jadi, jika suatu kelas memiliki@Conditional
nilainya mengembalikan false, itu tidak akan dikembalikan olehfindCandidateComponents
, bahkan jika itu cocok dengan filter pemindai. Ini melempar saya hari ini - saya akhirnya menggunakan solusi Jonathan di bawah ini sebagai gantinya.BeanDefinition
objek tidak menyediakan cara untuk mendapatkan kelas secara langsung. Hal terdekat tampaknya adalahgetBeanClassName
yang mengembalikan nama kelas yang berkualifikasi penuh, tetapi perilaku yang tepat dari metode ini tidak jelas. Juga, tidak jelas pemuat kelas mana yang ditemukan.Class<?> cl = Class.forName(beanDef.getBeanClassName());
farenda.com/spring/find-annotated-classesDan solusi lain adalah refleksi Google .
Ulasan cepat:
sumber
new Reflections("my.package").getTypesAnnotatedWith(MyAnnotation.class)
. disebut-sebut.Anda dapat menemukan kelas dengan penjelasan apa pun yang diberikan dengan ClassGraph , serta mencari kriteria menarik lainnya, misalnya kelas yang mengimplementasikan antarmuka yang diberikan. (Penafian, saya adalah penulis dari ClassGraph.) ClassGraph dapat membangun representasi abstrak dari seluruh grafik kelas (semua kelas, penjelasan, metode, parameter metode, dan bidang) dalam memori, untuk semua kelas di classpath, atau untuk kelas di paket yang masuk daftar putih, dan Anda dapat meminta grafik kelas itu sesuai keinginan. ClassGraph mendukung lebih banyak mekanisme spesifikasi classpath dan classloader daripada pemindai lain, dan juga bekerja dengan mulus dengan sistem modul JPMS baru, jadi jika Anda mendasarkan kode Anda pada ClassGraph, kode Anda akan portabel secara maksimal. Lihat API di sini.
sumber
Reflections
. Juga, jika Anda menggunakan jambu biji / etc dan ingin mengganti koleksi, semudah pie. Komentar yang bagus di dalam juga.Jika Anda menginginkan bobot yang sangat ringan (tanpa dependensi, API sederhana, file jar 15 kb) dan solusi yang sangat cepat , lihat
annotation-detector
di https://github.com/rmuller/infomas-aslPenafian: Saya penulis.
sumber
Anda dapat menggunakan Java Pluggable Annotation Processing API untuk menulis prosesor anotasi yang akan dieksekusi selama proses kompilasi dan akan mengumpulkan semua kelas beranotasi dan membuat file indeks untuk penggunaan runtime.
Ini adalah cara tercepat untuk melakukan penemuan kelas beranotasi karena Anda tidak perlu memindai classpath Anda saat runtime, yang biasanya operasi sangat lambat. Juga pendekatan ini berfungsi dengan classloader apa pun dan tidak hanya dengan URLClassLoaders yang biasanya didukung oleh pemindai runtime.
Mekanisme di atas sudah diterapkan di perpustakaan ClassIndex .
Untuk menggunakannya, beri anotasi anotasi khusus dengan meta-anotasi @IndexAnnotated . Ini akan membuat pada waktu kompilasi suatu file indeks: META-INF / annotations / com / test / YourCustomAnnotation daftar semua kelas yang dijelaskan. Anda dapat mengakses indeks saat runtime dengan menjalankan:
sumber
Apakah sudah terlambat untuk menjawab. Saya akan mengatakan, lebih baik menggunakan Libraries seperti ClassPathScanningCandidateComponentProvider atau seperti Scannotations
Tetapi bahkan setelah seseorang ingin mencobanya dengan classLoader, saya telah menulis sendiri untuk mencetak anotasi dari kelas dalam satu paket:
Dan dalam File config, Anda meletakkan nama paket dan menghapusnya ke kelas.
sumber
Dengan Spring Anda juga bisa menulis berikut ini menggunakan kelas AnnotationUtils. yaitu:
Untuk detail lebih lanjut dan semua metode yang berbeda, periksa dokumen resmi: https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/core/annotation/AnnotationUtils.html
sumber
null
nilai sebagai parameter kedua (yang mendefinisikan kelas, di mana hierarki warisan Spring akan memindai kelas yang menggunakan Anotasi), Anda akan mendapatkan balasannull
, sesuai dengan implementasinya.Ada komentar yang bagus dari zapp yang memenuhi semua jawaban itu:
sumber
Classloader API tidak memiliki metode "enumerate", karena pemuatan kelas adalah aktivitas "sesuai permintaan" - Anda biasanya memiliki ribuan kelas di classpath Anda, hanya sebagian kecil yang akan diperlukan (rt.jar sendiri adalah 48MB saat ini!).
Jadi, bahkan jika Anda dapat menghitung semua kelas, ini akan sangat memakan waktu dan memori.
Pendekatan sederhananya adalah dengan mendaftarkan kelas-kelas yang bersangkutan dalam file setup (xml atau apa pun yang sesuai dengan keinginan Anda); jika Anda ingin melakukan ini secara otomatis, batasi diri Anda pada satu JAR atau satu direktori kelas.
sumber
Google Reflection jika Anda ingin menemukan antarmuka juga.
Spring
ClassPathScanningCandidateComponentProvider
tidak menemukan antarmuka.sumber
Google Refleksi tampaknya jauh lebih cepat daripada Spring. Menemukan permintaan fitur ini yang mengatasi perbedaan ini: http://www.opensaga.org/jira/browse/OS-738
Ini adalah alasan untuk menggunakan Refleksi karena waktu startup aplikasi saya sangat penting selama pengembangan. Refleksi tampaknya juga sangat mudah digunakan untuk kasus penggunaan saya (temukan semua pelaksana antarmuka).
sumber
Jika Anda mencari alternatif untuk refleksi, saya ingin merekomendasikan Panda Utilities - AnnotationsScanner . Ini adalah pemindai yang bebas-Jambu (memiliki ~ 3 MB, Panda Utilities memiliki ~ 200kb) berdasarkan kode sumber perpustakaan refleksi.
Ini juga didedikasikan untuk pencarian berbasis masa depan. Jika Anda ingin memindai beberapa kali menyertakan sumber atau bahkan menyediakan API, yang memungkinkan seseorang memindai classpath saat ini,
AnnotationsScannerProcess
semua cache diambilClassFiles
, sehingga sangat cepat.Contoh
AnnotationsScanner
penggunaan sederhana :sumber
Musim semi memiliki sesuatu yang disebut
AnnotatedTypeScanner
kelas.Kelas ini digunakan secara internal
Kelas ini memiliki kode untuk pemindaian aktual sumber daya classpath . Ini dilakukan dengan menggunakan metadata kelas yang tersedia saat runtime.
Seseorang dapat dengan mudah memperluas kelas ini atau menggunakan kelas yang sama untuk pemindaian. Di bawah ini adalah definisi konstruktor.
sumber