Injeksi Konstruktor di Musim Semi dengan Lombok

1. Perkenalan

Lombok adalah perpustakaan yang sangat berguna untuk mengatasi kode boilerplate. Jika Anda belum terbiasa, saya sangat menyarankan untuk melihat tutorial sebelumnya - Pengenalan Proyek Lombok.

Dalam artikel ini, kami akan menunjukkan kegunaannya saat dikombinasikan dengan Injeksi Ketergantungan Berbasis Konstruktor Spring .

2. Injeksi Ketergantungan Berbasis Konstruktor

Cara yang baik untuk menghubungkan dependensi di Spring menggunakan Injeksi Dependensi berbasis onstruktor . Pendekatan ini memaksa kita untuk secara eksplisit meneruskan dependensi komponen ke konstruktor.

Berbeda dengan Injeksi Ketergantungan Berbasis Lapangan , ini juga memberikan sejumlah keuntungan:

  • tidak perlu membuat komponen konfigurasi khusus pengujian - dependensi dimasukkan secara eksplisit dalam konstruktor
  • desain yang konsisten - semua dependensi yang diperlukan ditekankan dan dijaga oleh definisi konstruktor
  • tes unit sederhana - mengurangi overhead Spring Framework
  • mendapatkan kembali kebebasan untuk menggunakan kata kunci akhir

Namun, karena kebutuhan untuk menulis konstruktor, itu digunakan untuk mengarah ke basis kode yang jauh lebih besar. Pertimbangkan dua contoh GreetingService dan FarewellService:

@Component public class GreetingService { @Autowired private Translator translator; public String produce() { return translator.translate("hello"); } }
@Component public class FarewellService { private final Translator translator; public FarewellService(Translator translator) { this.translator = translator; } public String produce() { return translator.translate("bye"); } }

Pada dasarnya, kedua komponen melakukan hal yang sama - mereka memanggil Penerjemah yang dapat dikonfigurasi dengan kata khusus tugas.

Variasi kedua, bagaimanapun, jauh lebih disamarkan karena boilerplate konstruktor yang tidak benar-benar membawa nilai apa pun ke kode.

Dalam rilis Spring terbaru, konstruktornya tidak perlu dianotasi dengan anotasi @Autowired .

3. Injeksi Konstruktor Dengan Lombok

Dengan Lombok , dimungkinkan untuk menghasilkan konstruktor untuk semua bidang kelas (dengan @AllArgsConstructor ) atau semua bidang kelas akhir (dengan @RequiredArgsConstructor ). Selain itu, jika Anda masih memerlukan konstruktor kosong, Anda dapat menambahkan anotasi @NoArgsConstructor tambahan .

Mari buat komponen ketiga, analog dengan dua sebelumnya:

@Component @RequiredArgsConstructor public class ThankingService { private final Translator translator; public String produce() { return translator.translate("thank you"); } }

Anotasi di atas akan menyebabkan Lombok membuat konstruktor untuk kita:

@Component public class ThankingService { private final Translator translator; public String thank() { return translator.translate("thank you"); } /* Generated by Lombok */ public ThankingService(Translator translator) { this.translator = translator; } }

4. Banyak Konstruktor

Konstruktor tidak harus dianotasi selama hanya ada satu di komponen dan Spring dapat memilihnya dengan jelas sebagai yang tepat untuk membuat instance objek baru. Begitu ada lebih banyak, Anda juga perlu memberi anotasi yang akan digunakan oleh wadah IoC.

Pertimbangkan contoh ApologizeService :

@Component @RequiredArgsConstructor public class ApologizeService { private final Translator translator; private final String message; @Autowired public ApologizeService(Translator translator) { this(translator, "sorry"); } public String produce() { return translator.translate(message); } }

Komponen di atas secara opsional dapat dikonfigurasi dengan bidang pesan yang tidak dapat diubah setelah komponen dibuat (karena itu tidak ada penyetel ). Oleh karena itu, kami diminta untuk menyediakan dua konstruktor - satu dengan konfigurasi penuh dan yang lainnya dengan nilai default pesan yang implisit .

Kecuali salah satu konstruktor dianotasi dengan @Autowired , @Inject atau @Resource , Spring akan menampilkan error:

Failed to instantiate [...]: No default constructor found;

Jika kita ingin membuat anotasi pada konstruktor yang dibuat oleh Lombok , kita harus meneruskan anotasi dengan parameter onConstructor dari @AllArgsConstructor :

@Component @RequiredArgsConstructor(onConstructor = @__(@Autowired)) public class ApologizeService { // ... }

The onConstructor parameter menerima array penjelasan (atau penjelasan tunggal seperti dalam contoh khusus ini) yang akan mengenakan konstruktor yang dihasilkan. Idiom garis bawah ganda telah diperkenalkan karena masalah kompatibilitas ke belakang. Menurut dokumentasi:

Alasan dari sintaks yang aneh adalah untuk membuat fitur ini berfungsi di kompiler javac 7; yang @__jenis adalah sebuah referensi penjelasan dengan jenis anotasi __(double underscore) yang tidak benar-benar ada; hal ini membuat javac 7 delay membatalkan proses kompilasi karena error karena kemungkinan pemroses anotasi nantinya akan membuat __tipe tersebut.

5. Ringkasan

Dalam tutorial ini, kami menunjukkan bahwa tidak perlu mendukung DI berbasis lapangan daripada DI berbasis konstruktor dalam hal peningkatan kode boilerplate.

Berkat Lombok, dimungkinkan untuk mengotomatiskan pembuatan kode umum tanpa berdampak pada kinerja pada waktu proses, menyingkat kode yang panjang dan mengaburkan menjadi penggunaan anotasi baris tunggal.

Kode yang digunakan selama tutorial tersedia di GitHub.