Panduan ke Perpustakaan Refleksi

1. Pengenalan

The Reflections perpustakaan berfungsi sebagai pengimbas classpath. Ia mengindeks metadata yang diimbas dan membolehkan kami mengemukakannya pada waktu berjalan. Ia juga dapat menyimpan maklumat ini, jadi kami dapat mengumpulkan dan menggunakannya pada bila-bila masa semasa projek kami, tanpa perlu mengimbas kembali jalan kelas itu lagi.

Dalam tutorial ini, kami akan menunjukkan cara mengkonfigurasi perpustakaan Reflections dan menggunakannya dalam projek Java kami.

2. Ketergantungan Maven

Untuk menggunakan Refleksi , kita perlu memasukkan kebergantungannya dalam projek kita:

 org.reflections reflections 0.9.11 

Kami dapat mencari versi terbaru perpustakaan di Maven Central.

3. Mengkonfigurasi Refleksi

Seterusnya, kita perlu mengkonfigurasi perpustakaan. Elemen utama konfigurasi adalah URL dan pengimbas.

URL memberitahu perpustakaan bahagian jalan kelas yang hendak diimbas, sedangkan pengimbas adalah objek yang mengimbas URL yang diberikan.

Sekiranya pengimbas tidak dikonfigurasi, perpustakaan menggunakan TypeAnnotationsScanner dan SubTypesScanner sebagai yang lalai.

3.1. Menambah URL

Kita dapat mengkonfigurasi Refleksi sama ada dengan menyediakan elemen konfigurasi sebagai parameter pembentuk varargs, atau dengan menggunakan objek ConfigurationBuilder .

Sebagai contoh, kita dapat menambahkan URL dengan memberi contoh Reflections menggunakan String yang mewakili nama paket, class, atau class loader:

Reflections reflections = new Reflections("com.baeldung.reflections"); Reflections reflections = new Reflections(MyClass.class); Reflections reflections = new Reflections(MyClass.class.getClassLoader());

Lebih-lebih lagi, kerana Refleksi mempunyai konstruktor varargs, kita dapat menggabungkan semua jenis konfigurasi di atas untuk mewujudkannya:

Reflections reflections = new Reflections("com.baeldung.reflections", MyClass.class);

Di sini, kami menambahkan URL dengan menentukan pakej dan kelas yang akan diimbas.

Kami dapat memperoleh hasil yang sama dengan menggunakan ConfigurationBuilder :

Reflections reflections = new Reflections(new ConfigurationBuilder() .setUrls(ClasspathHelper.forPackage("com.baeldung.reflections"))));

Bersama dengan kaedah forPackage () , Classp ath Helpe r menyediakan kaedah lain, seperti forClass () dan forClassLoader () , untuk menambahkan URL ke konfigurasi.

3.2. Menambah Pengimbas

Perpustakaan Reflections dilengkapi dengan banyak pengimbas terbina dalam:

  • FieldAnnotationsScanner - mencari anotasi medan
  • MethodParameterScanner - mengimbas kaedah / konstruktor, kemudian mengindeks parameter, dan mengembalikan anotasi jenis dan parameter
  • MethodParameterNamesScanner - memeriksa kaedah / pembina, kemudian mengindeks nama parameter
  • TypeElementsScanner - memeriksa bidang dan kaedah, kemudian menyimpan nama yang layak sepenuhnya sebagai kunci, dan elemen sebagai nilai
  • MemberUsageScanner - mengimbas kaedah penggunaan / konstruktor / bidang
  • TypeAnnotationsScanner - mencari anotasi runtime kelas
  • SubTypesScanner - mencari kelas super dan antara muka kelas, yang membolehkan carian terbalik untuk subjenis
  • MethodAnnotationsScanner - mengimbas anotasi kaedah
  • ResourcesScanner - mengumpulkan semua sumber bukan kelas dalam koleksi

Kita boleh menambahkan pengimbas ke konfigurasi sebagai parameter konstruktor Refleksi .

Sebagai contoh, mari kita tambahkan dua pengimbas pertama dari senarai di atas:

Reflections reflections = new Reflections("com.baeldung.reflections"), new FieldAnnotationsScanner(), new MethodParameterScanner());

Sekali lagi, kedua-dua pengimbas dapat dikonfigurasi dengan menggunakan kelas penolong ConfigurationBuilder :

Reflections reflections = new Reflections(new ConfigurationBuilder() .setUrls(ClasspathHelper.forPackage("com.baeldung.reflections")) .setScanners(new FieldAnnotationsScanner(), new MethodParameterScanner()));

3.3. Menambah Perkhidmatan Pelaksana

Sebagai tambahan kepada URL dan pengimbas, Reflections memberi kita kemungkinan untuk mengimbas classpath secara asinkron dengan menggunakan ExecutorService .

Kita boleh menambahkannya sebagai parameter konstruktor Refleksi , atau melalui ConfigurationBuilder :

Reflections reflections = new Reflections(new ConfigurationBuilder() .setUrls(ClasspathHelper.forPackage("com.baeldung.reflections")) .setScanners(new SubTypesScanner(), new TypeAnnotationsScanner()) .setExecutorService(Executors.newFixedThreadPool(4)));

Pilihan lain adalah dengan memanggil kaedah useParallelExecutor () . Kaedah ini mengkonfigurasi FixedThreadPool ExecutorService lalai dengan ukuran yang sama dengan bilangan pemproses teras yang ada.

3.4. Menambah Penapis

Elemen konfigurasi penting lain adalah penapis. Penapis memberitahu pengimbas apa yang harus disertakan, dan apa yang harus dikecualikan, semasa mengimbas jalan kelas .

Sebagai gambaran, kita dapat mengkonfigurasi penapis untuk mengecualikan pengimbasan pakej ujian:

Reflections reflections = new Reflections(new ConfigurationBuilder() .setUrls(ClasspathHelper.forPackage("com.baeldung.reflections")) .setScanners(new SubTypesScanner(), new TypeAnnotationsScanner()) .filterInputsBy(new FilterBuilder().excludePackage("com.baeldung.reflections.test")));

Sekarang, hingga saat ini, kami telah membuat tinjauan ringkas mengenai pelbagai elemen konfigurasi Refleksi . Seterusnya, kita akan melihat cara menggunakan perpustakaan.

4. Menyoal Menggunakan Refleksi

Setelah memanggil salah satu konstruktor Refleksi , pengimbas yang dikonfigurasi mengimbas semua URL yang disediakan. Kemudian, untuk setiap pengimbas, perpustakaan meletakkan hasilnya di kedai Multimap . Akibatnya, untuk menggunakan Refleksi , kita perlu menanyakan kedai ini dengan memanggil kaedah pertanyaan yang disediakan.

Mari lihat beberapa contoh kaedah pertanyaan ini.

4.1. Subjenis

Mari mulakan dengan mengambil semua pengimbas yang disediakan oleh Reflections :

public Set
    
      getReflectionsSubTypes() { Reflections reflections = new Reflections( "org.reflections", new SubTypesScanner()); return reflections.getSubTypesOf(Scanner.class); }
    

4.2. Jenis Anotasi

Seterusnya, kita dapat semua kelas dan antara muka yang menerapkan anotasi yang diberikan.

Oleh itu, mari dapatkan semula semua antara muka fungsional pakej fungsi java.util.fungsi :

public Set
    
      getJDKFunctinalInterfaces() { Reflections reflections = new Reflections("java.util.function", new TypeAnnotationsScanner()); return reflections.getTypesAnnotatedWith(FunctionalInterface.class); }
    

4.3. Kaedah Anotasi

Sekarang, mari kita gunakan MethodAnnotationsScanner untuk mendapatkan semua kaedah yang diberi penjelasan dengan anotasi tertentu:

public Set getDateDeprecatedMethods() { Reflections reflections = new Reflections( "java.util.Date", new MethodAnnotationsScanner()); return reflections.getMethodsAnnotatedWith(Deprecated.class); }

4.4. Pembina Beranotasi

Juga, kita dapat semua konstruktor yang tidak digunakan

public Set getDateDeprecatedConstructors() { Reflections reflections = new Reflections( "java.util.Date", new MethodAnnotationsScanner()); return reflections.getConstructorsAnnotatedWith(Deprecated.class); }

4.5. Parameter Kaedah

Selain itu, kita dapat menggunakan MethodParameterScanner untuk mencari semua kaedah dengan jenis parameter yang diberikan:

public Set getMethodsWithDateParam() { Reflections reflections = new Reflections( java.text.SimpleDateFormat.class, new MethodParameterScanner()); return reflections.getMethodsMatchParams(Date.class); }

4.6. Jenis Pengembalian Kaedah

Selanjutnya, kita juga dapat menggunakan pengimbas yang sama untuk mendapatkan semua kaedah dengan jenis pengembalian yang diberikan.

Let's imagine that we want to find all the methods of the SimpleDateFormat that return void:

public Set getMethodsWithVoidReturn() { Reflections reflections = new Reflections( "java.text.SimpleDateFormat", new MethodParameterScanner()); return reflections.getMethodsReturn(void.class); }

4.7. Resources

Finally, let's use the ResourcesScanner to look for a given filename in our classpath:

public Set getPomXmlPaths() { Reflections reflections = new Reflections(new ResourcesScanner()); return reflections.getResources(Pattern.compile(".*pom\\.xml")); }

4.8. Additional Query Methods

The above were but a handful of examples showing how to use Reflections' query methods. Yet, there are other query methods that we haven't covered here:

  • getMethodsWithAnyParamAnnotated
  • getConstructorsMatchParams
  • getConstructorsWithAnyParamAnnotated
  • getFieldsAnnotatedWith
  • getMethodParamNames
  • getConstructorParamNames
  • getFieldUsage
  • getMethodUsage
  • getConstructorUsage

5. Integrating Reflections into a Build Lifecycle

Kami dapat menggabungkan Refleksi dengan mudah ke dalam Maven kami dengan menggunakan gmavenplus-plugin .

Mari konfigurasikannya untuk menyimpan hasil imbasan ke fail:

 org.codehaus.gmavenplus gmavenplus-plugin 1.5   generate-resources  execute          

Kemudian, dengan memanggil kaedah kumpulkan () , kita dapat mengambil hasil yang disimpan dan membuatnya tersedia untuk penggunaan lebih lanjut, tanpa harus melakukan imbasan baru:

Reflections reflections = isProduction() ? Reflections.collect() : new Reflections("com.baeldung.reflections");

6. Kesimpulannya

Dalam artikel ini, kami meneroka perpustakaan Refleksi . Kami merangkumi pelbagai elemen konfigurasi dan penggunaannya. Dan, akhirnya, kami melihat bagaimana mengintegrasikan Reflections ke dalam kitaran hidup projek Maven.

Seperti biasa, kod lengkap boleh didapati di GitHub.