Bidang yang dianotasi @Autowired
adalah null
karena Spring tidak tahu tentang salinan MileageFeeCalculator
yang Anda buat dengan new
dan tidak tahu untuk autowire itu.
Kontainer Spring Inversion of Control (IoC) memiliki tiga komponen logis utama: registri (disebut Windows 7)ApplicationContext
) komponen (kacang) yang tersedia untuk digunakan oleh aplikasi, sistem konfigurator yang menyuntikkan dependensi objek ke dalamnya dengan mencocokkan dependensi dengan kacang dalam konteks, dan pemecah ketergantungan yang dapat melihat konfigurasi banyak kacang yang berbeda dan menentukan bagaimana membuat instantiate dan mengkonfigurasinya dalam urutan yang diperlukan.
Kontainer IoC bukanlah sihir, dan tidak memiliki cara untuk mengetahui tentang objek-objek Java kecuali jika Anda memberitahukannya. Ketika Anda menelepon new
, JVM instantiate salinan objek baru dan menyerahkannya langsung kepada Anda - tidak pernah melewati proses konfigurasi. Ada tiga cara untuk mengonfigurasi kacang Anda.
Saya telah memposting semua kode ini, menggunakan Spring Boot untuk diluncurkan, di proyek GitHub ini ; Anda dapat melihat proyek yang berjalan penuh untuk setiap pendekatan untuk melihat semua yang Anda butuhkan untuk membuatnya bekerja. Tag dengan NullPointerException
:nonworking
Suntikkan kacang Anda
Opsi yang paling disukai adalah membiarkan Spring mengotomatiskan semua kacang Anda; ini membutuhkan jumlah kode paling sedikit dan merupakan yang paling bisa dikelola. Untuk membuat autowiring berfungsi seperti yang Anda inginkan, autowire juga MileageFeeCalculator
seperti ini:
@Controller
public class MileageFeeController {
@Autowired
private MileageFeeCalculator calc;
@RequestMapping("/mileage/{miles}")
@ResponseBody
public float mileageFee(@PathVariable int miles) {
return calc.mileageCharge(miles);
}
}
Jika Anda perlu membuat instance baru objek layanan Anda untuk permintaan yang berbeda, Anda masih bisa menggunakan injeksi dengan menggunakan lingkup bean Spring .
Tag yang berfungsi dengan menyuntikkan @MileageFeeCalculator
objek layanan:working-inject-bean
Gunakan @Configurable
Jika Anda benar-benar membutuhkan objek yang dibuat dengan new
autowired, Anda dapat menggunakan @Configurable
anotasi Spring bersama dengan tenun waktu kompilasi AspectJ untuk menyuntikkan objek Anda. Pendekatan ini menyisipkan kode ke konstruktor objek Anda yang memberitahu Spring bahwa itu dibuat sehingga Spring dapat mengkonfigurasi instance baru. Ini membutuhkan sedikit konfigurasi dalam build Anda (seperti kompilasi dengan ajc
) dan menyalakan penangan konfigurasi runtime Spring ( @EnableSpringConfigured
dengan sintaks JavaConfig). Pendekatan ini digunakan oleh sistem Rekaman Aktif Roo untuk memungkinkan new
instance dari entitas Anda untuk mendapatkan informasi persistensi yang diperlukan disuntikkan.
@Service
@Configurable
public class MileageFeeCalculator {
@Autowired
private MileageRateService rateService;
public float mileageCharge(final int miles) {
return (miles * rateService.ratePerMile());
}
}
Tag yang berfungsi dengan menggunakan @Configurable
pada objek layanan:working-configurable
Pencarian kacang manual: tidak disarankan
Pendekatan ini hanya cocok untuk berinteraksi dengan kode lawas dalam situasi khusus. Hampir selalu lebih disukai untuk membuat kelas adaptor tunggal yang dapat diautow oleh autovire dan kode lawas dapat dipanggil, tetapi dimungkinkan untuk secara langsung menanyakan konteks aplikasi Spring untuk sebuah kacang.
Untuk melakukan ini, Anda memerlukan kelas yang Spring dapat memberikan referensi ke ApplicationContext
objek:
@Component
public class ApplicationContextHolder implements ApplicationContextAware {
private static ApplicationContext context;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
context = applicationContext;
}
public static ApplicationContext getContext() {
return context;
}
}
Kemudian kode lawas Anda dapat memanggil getContext()
dan mengambil kacang yang dibutuhkan:
@Controller
public class MileageFeeController {
@RequestMapping("/mileage/{miles}")
@ResponseBody
public float mileageFee(@PathVariable int miles) {
MileageFeeCalculator calc = ApplicationContextHolder.getContext().getBean(MileageFeeCalculator.class);
return calc.mileageCharge(miles);
}
}
Tag yang berfungsi secara manual mencari objek layanan dalam konteks Spring: working-manual-lookup
F
disebut di dalam konstruktor kacang lainS
. Dalam hal ini, lewati kacang yang diperlukanF
sebagai parameter untukS
konstruktor kacang lainnya dan beri keterangan pada konstruktorS
dengan@Autowire
. Ingat untuk membubuhi keterangan kelas kacang pertamaF
dengan@Component
.