Injeksi Konstruktor dan Dependensi Sirkular
Utamakan injeksi konstruktor agar mudah diuji, deteksi dependensi sirkular, dan atasi dengan @Lazy.
Injeksi Konstruktor dan Dependensi Sirkular adalah pelajaran Java Academy gratis di CoddyKit. Ini adalah pelajaran 4 dari 4. Kamu bisa membaca pelajaran lengkapnya di bawah secara gratis — lalu praktikkan langsung di browser dengan editor kode bawaan dan tutor AI 24/7. Ini adalah bagian dari jalur belajar Java Academy, dan progresmu tersinkronisasi di web dan aplikasi CoddyKit. Kursus Java Academy mencakup 4 pelajaran total.
Tiga Jenis Injeksi
Spring mendukung injeksi konstruktor (disarankan), injeksi atribut (@Autowired pada atribut), dan injeksi penyetel. Injeksi konstruktor lebih disukai karena kemudahan pengujian dan kekekalan.
Injeksi Konstruktor
Deklarasikan dependensi sebagai parameter konstruktor. Spring menyuntikkannya secara otomatis. Jika hanya ada satu konstruktor, @Autowired bersifat opsional (Spring Boot 2.1+).
@Service
public class OrderService {
private final OrderRepository repo;
private final EmailService email;
// @Autowired is optional when there is only one constructor
public OrderService(OrderRepository repo, EmailService email) {
this.repo = repo;
this.email = email;
}
}Mengapa Injeksi Konstruktor Lebih Disukai
Injeksi konstruktor: (1) dependensi bersifat final — tidak dapat diubah, (2) kelas selalu diinisialisasi sepenuhnya, (3) tidak ada dependensi Spring dalam pengujian unit — cukup panggil new OrderService(mockRepo, mockEmail).
// Unit test — no Spring context needed:
OrderRepository mockRepo = mock(OrderRepository.class);
EmailService mockEmail = mock(EmailService.class);
OrderService service = new OrderService(mockRepo, mockEmail);
// Test service logic directlyInjeksi Atribut (Hindari)
Injeksi atribut dengan @Autowired memang ringkas, tetapi bermasalah: atribut tidak dapat bersifat final, komponen tidak diinisialisasi sepenuhnya setelah konstruksi, dan pengujian unit memerlukan Spring atau pembantu refleksi Mockito.
// Avoid in production code:
@Service
public class UserService {
@Autowired // hidden dependency
private UserRepository repo; // cannot be final
}Injeksi Penyetel untuk Dependensi Opsional
Gunakan injeksi penyetel untuk dependensi opsional yang memiliki nilai bawaan yang masuk akal — beri anotasi pada metode penyetel dengan @Autowired(required = false).
@Service
public class NotificationService {
private SmsSender smsSender; // optional
@Autowired(required = false)
public void setSmsSender(SmsSender s) { this.smsSender = s; }
}Apa Itu Dependensi Sirkular?
Dependensi sirkular terjadi ketika A memerlukan B dan B memerlukan A (secara langsung atau melalui perantara). Spring mendeteksinya saat aplikasi dimulai dan melempar BeanCurrentlyInCreationException.
// CIRCULAR:
@Service class A { A(B b) {} }
@Service class B { B(A a) {} }
// Spring throws: BeanCurrentlyInCreationException: Is there an unresolvable circular reference?Memutus Sirkularitas: Refaktor ke Layanan Ketiga
Perbaikan yang paling bersih adalah mengekstrak logika bersama ke layanan ketiga yang tidak bergantung secara siklik pada A maupun B.
// Before: A <-> B
// After: A -> C, B -> C (no cycle)
@Service class SharedLogic { ... }
@Service class A { A(SharedLogic s) {} }
@Service class B { B(SharedLogic s) {} }Memutus Sirkularitas: @Lazy
Beri anotasi @Lazy pada salah satu titik injeksi. Spring segera membuat proksi untuk B; B yang sebenarnya baru dibuat ketika A pertama kali memanggil metode pada B.
@Service
public class A {
private final B b;
public A(@Lazy B b) { this.b = b; } // breaks the cycle
}Memutus Sirkularitas: Pencarian melalui ApplicationContext
Injeksikan ApplicationContext ke salah satu komponen, lalu cari komponen lainnya secara tertunda melalui context.getBean() — tetapi cara ini mengurangi kemudahan pengujian dan kejelasan.
@Service
public class A implements ApplicationContextAware {
private ApplicationContext ctx;
public void setApplicationContext(ApplicationContext c) { this.ctx = c; }
public void doWork() { ctx.getBean(B.class).help(); }
}Injeksi Penyetel untuk Memutus Sirkularitas
Komponen yang diinjeksi melalui penyetel dibuat lebih dahulu (konstruksi berhasil), lalu dependensinya ditetapkan. Hal ini memungkinkan dependensi sirkular dengan mengorbankan kemampuan untuk diubah.
@Service
public class A {
private B b;
@Autowired public void setB(B b) { this.b = b; } // Spring sets after construction
}spring.main.allow-circular-references (Spring Boot 2.6+)
Spring Boot 2.6+ tidak mengizinkan dependensi sirkular secara bawaan. Aktifkan secara eksplisit hanya sebagai langkah sementara saat melakukan refaktor: spring.main.allow-circular-references=true.
# application.properties (temporary workaround only):
spring.main.allow-circular-references=truePemeriksaan Singkat
Mengapa injeksi konstruktor lebih disukai daripada injeksi atribut?
Ringkasan
Utamakan injeksi konstruktor: tidak dapat diubah, mudah diuji, dan eksplisit. Hindari injeksi atribut. Gunakan @Lazy atau ekstrak layanan bersama untuk memutus dependensi sirkular. Spring Boot 2.6+ menandai referensi sirkular saat aplikasi dimulai — anggap sebagai peringatan desain.
Pertanyaan yang Sering Diajukan
Apakah pelajaran “Injeksi Konstruktor dan Dependensi Sirkular” gratis?
Ya — teks lengkap “Injeksi Konstruktor dan Dependensi Sirkular” gratis dibaca di sini di web. Untuk praktiknya secara interaktif (editor kode bawaan dan tutor AI 24/7) dan buka sisa kursus Java Academy, upgrade ke CoddyKit PRO. Kursus Java Academy mencakup 4 pelajaran total.
Apa yang akan aku pelajari di “Injeksi Konstruktor dan Dependensi Sirkular”?
Utamakan injeksi konstruktor agar mudah diuji, deteksi dependensi sirkular, dan atasi dengan @Lazy. Kamu berlatih Java Academy dengan kode praktik yang langsung kamu jalankan di browser, dan tutor AI 24/7 menjawab pertanyaanmu saat kamu mengerjakan pelajaran ini.
Apakah aku perlu pengalaman untuk memulai Java Academy?
Tidak diperlukan pengalaman sebelumnya. Java Academy di CoddyKit dirancang untuk pemula hingga pelajar tingkat lanjut, jadi kamu bisa memulai di sini atau dari awal dan belajar sesuai kecepatan kamu sendiri. Ini adalah pelajaran 4 dari 4.
Berapa lama pelajaran “Injeksi Konstruktor dan Dependensi Sirkular” memakan waktu?
Sebagian besar pelajaran CoddyKit memakan waktu sekitar 5–10 menit. Setiap pelajaran ringkas dan interaktif, jadi kamu membuat kemajuan stabil dan melanjutkan dari tempat kamu tinggalkan di web dan aplikasi.
Bisakah aku menulis dan menjalankan kode dalam pelajaran Java Academy ini?
Ya. Setiap pelajaran Java Academy menyertakan editor kode bawaan, jadi kamu menulis dan menjalankan kode nyata langsung di browser dan mendapatkan umpan balik AI instan — tidak diperlukan penyiapan lokal.
Semua pelajaran dalam kursus ini
- Konfigurasi Otomatis dan Starter Spring Boot
- Properti Aplikasi dan Profil
- Penyambungan Bean: @Component, @Service, @Repository
- Injeksi Konstruktor dan Dependensi Sirkular