Trường được chú thích @Autowired
là null
bởi vì Spring không biết về bản sao MileageFeeCalculator
mà bạn đã tạo new
và không biết để tự động xác định nó.
Bộ chứa Spring Inversion of Control (IoC) có ba thành phần logic chính: một thanh ghi (được gọi là ApplicationContext
) các thành phần (đậu) có sẵn để ứng dụng sử dụng, một hệ thống cấu hình đưa các phụ thuộc của đối tượng vào chúng bằng cách khớp với phụ thuộc với các bean trong ngữ cảnh và một bộ giải phụ thuộc có thể xem xét cấu hình của nhiều loại đậu khác nhau và xác định cách khởi tạo và cấu hình chúng theo thứ tự cần thiết.
Bộ chứa IoC không phải là ma thuật và nó không có cách nào biết về các đối tượng Java trừ khi bạn bằng cách nào đó thông báo cho chúng về chúng. Khi bạn gọi new
, JVM khởi tạo một bản sao của đối tượng mới và trao thẳng cho bạn - nó không bao giờ trải qua quá trình cấu hình. Có ba cách để bạn có thể cấu hình hạt đậu của mình.
Tôi đã đăng tất cả các mã này, sử dụng Spring Boot để khởi chạy, tại dự án GitHub này ; bạn có thể xem xét một dự án đang chạy đầy đủ cho từng phương pháp để xem mọi thứ bạn cần để làm cho nó hoạt động. Gắn thẻ với NullPointerException
:nonworking
Tiêm đậu của bạn
Tùy chọn thích hợp nhất là để Spring tự động tất cả các loại đậu của bạn; điều này đòi hỏi số lượng mã ít nhất và có thể duy trì nhiều nhất. Để thực hiện công việc tự động như bạn muốn, cũng MileageFeeCalculator
tự động thực hiện như thế này:
@Controller
public class MileageFeeController {
@Autowired
private MileageFeeCalculator calc;
@RequestMapping("/mileage/{miles}")
@ResponseBody
public float mileageFee(@PathVariable int miles) {
return calc.mileageCharge(miles);
}
}
Nếu bạn cần tạo một phiên bản mới của đối tượng dịch vụ cho các yêu cầu khác nhau, bạn vẫn có thể sử dụng phép tiêm bằng cách sử dụng phạm vi Spring bean .
Tag hoạt động bằng cách tiêm @MileageFeeCalculator
đối tượng dịch vụ:working-inject-bean
Sử dụng @Configurable
Nếu bạn thực sự cần các đối tượng được tạo new
để tự động, bạn có thể sử dụng @Configurable
chú thích Spring cùng với dệt thời gian biên dịch AspectJ để tiêm các đối tượng của bạn. Cách tiếp cận này chèn mã vào hàm tạo của đối tượng để thông báo cho Spring rằng nó đang được tạo để Spring có thể định cấu hình thể hiện mới. Điều này đòi hỏi một chút cấu hình trong bản dựng của bạn (chẳng hạn như biên dịch với ajc
) và bật trình xử lý cấu hình thời gian chạy của Spring ( @EnableSpringConfigured
với cú pháp JavaConfig). Cách tiếp cận này được sử dụng bởi hệ thống Bản ghi hoạt động của Roo để cho phép các new
phiên bản của các thực thể của bạn nhận được thông tin lưu giữ cần thiết được đưa vào.
@Service
@Configurable
public class MileageFeeCalculator {
@Autowired
private MileageRateService rateService;
public float mileageCharge(final int miles) {
return (miles * rateService.ratePerMile());
}
}
Thẻ hoạt động bằng cách sử dụng @Configurable
trên đối tượng dịch vụ:working-configurable
Tra cứu bằng tay: không nên
Cách tiếp cận này chỉ phù hợp để giao tiếp với mã kế thừa trong các tình huống đặc biệt. Gần như luôn luôn thích hợp hơn để tạo một lớp bộ điều hợp đơn mà Spring có thể tự động và mã kế thừa có thể gọi, nhưng có thể trực tiếp yêu cầu bối cảnh ứng dụng Spring cho một bean.
Để làm điều này, bạn cần một lớp mà Spring có thể đưa ra một tham chiếu đến ApplicationContext
đối tượng:
@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;
}
}
Sau đó, mã kế thừa của bạn có thể gọi getContext()
và lấy các hạt mà nó cần:
@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);
}
}
Thẻ hoạt động bằng cách tìm kiếm thủ công đối tượng dịch vụ trong ngữ cảnh Spring: working-manual-lookup
F
được gọi bên trong hàm tạo của bean khácS
. Trong trường hợp này, chuyển bean yêu cầuF
làm tham số cho hàm tạo bean khácS
và chú thích hàm tạo củaS
với@Autowire
. Nhớ chú thích lớp của bean đầu tiênF
với@Component
.