Vấn đề
Khi làm việc với Spring Boot, chúng ta thường xuyên gặp khái niệm IoC và Dependency Injection (DI) - tức là quản lý và tiêm các phụ thuộc vào trong ứng dụng. Câu hỏi đặt ra là: làm thế nào để thực hiện việc tiêm Bean một cách chính xác?
Trong Spring Framework, có những cách nào để đăng ký và tiêm một Bean? Annotation @Resource có phải là tính năng của Spring hay là từ JDK (Java Development Kit)? Và quan trọng hơn, Spring dựa trên tiêu chí nào để xác định Bean nào sẽ được tiêm vào một thuộc tính cụ thể?
Câu trả lời
- Các phương thức thực hiện tiêm Bean
Sử dụng annotation trong Spring
IoC (Inversion of Control) còn được gọi là Dependency Injection (DI). Đây là quá trình mô tả cách một đối tượng được định nghĩa và các phụ thuộc của nó được xử lý. Các đối tượng phụ thuộc có thể được tiêm thông qua constructor, tham số của factory method, hoặc các thuộc tính. Khi đối tượng được khởi tạo, các phụ thuộc sẽ được tiêm vào - đây là cơ chế "đảo ngược" so với cách truyền thống.
1. Trong Spring, một class được đăng ký làm Bean thông qua annotation
@Component: Annotation này đánh dấu một class là thành phần của Spring, cho phép Spring quản lý và tự động quét class đó.
Khi thêm @Component vào một class nằm trong package được quét bởi @ComponentScan, hoặc định nghĩa @Bean trong configuration class, class đó sẽ được đăng ký vào Spring Container.
@Component
public class ProductService {
}
Hoặc có thể định nghĩa Bean trực tiếp trong class cấu hình:
@Configuration
@ComponentScan("com.example.shop")
public class AppConfig {
@Bean
public ProductService productService() {
return new ProductService();
}
}
2. Khi một Bean cần sử dụng Bean khác, ta cần thực hiện Dependency Injection
@Component
public class OrderService {
private ProductService productService;
@Autowired
public OrderService(ProductService productService) {
this.productService = productService;
}
@Override
public String toString() {
return "OrderService{productService=" + productService + '}';
}
}
Để sử dụng một Bean từ bên trong Bean khác, ta cần sử dụng annotation @Autowired để thực hiện tiêm phụ thuộc tự động.
Các annotation thường dùng
| Annotation | Ý nghĩa |
|---|---|
| @Configuration | Đánh dấu class là class cấu hình |
| @ComponentScan("package") | Chỉ định package cần quét để tìm các annotation |
| @Autowired | Tự động tiêm Bean, có thể đặt trên thuộc tính, phương thức hoặc constructor |
| @Component | Đánh dấu class là Bean, đưa vào container, mặc định là singleton |
| @Bean | Định nghĩa một Bean object, thêm vào Spring Container |
| @Order(số) | Thứ tự ưu tiên khi khởi tạo Bean, số nhỏ hơn có ưu tiên cao hơn |
- Sự khác biệt giữa @Autowired và @Resource?
@Autowired là annotation của Spring, thực hiện tiêm theo kiểu (byType). @Resource là annotation của Java EE (Jakarta EE), thực hiện tiêm theo tên (byName).
Vì @Resource thuộc tiêu chuẩn Java EE, nên nếu sử dụng các IoC container khác không phải Spring, annotation này vẫn tương thích được.
Vậy @Resource dựa trên quy tắc nào để xác định Bean tiêm vào?
Spring cung cấp 4 loại auto-wiring:
byName: Thực hiện khớp theo tên. Ví dụ, nếu class Customer có thuộc tính tên là "paymentProcessor", và trong container có Bean tên là "paymentProcessor", Spring sẽ tự động tiêm Bean đó vào thuộc tính tương ứng.tags
Hai phương thức tiêm Bean: @Resource và @Autowired Vấn đề
Khi làm việc với Spring Boot, chúng ta thường xuyên gặp khái niệm IoC và Dependency Injection (DI) - tức là quản lý và tiêm các phụ thuộc vào trong ứng dụng. Câu hỏi đặt ra là: làm thế nào để thực hiện việc tiêm Bean một cách chính xác?
Trong Spring Framework, có những cách nào để đăng ký và tiêm một Bean? Annotation @Resource có phải là tính năng của Spring hay là từ JDK (Java Development Kit)? Và quan trọng hơn, Spring dựa trên tiêu chí nào để xác định Bean nào sẽ được tiêm vào một thuộc tính cụ thể?
Câu trả lời
- Các phương thức thực hiện tiêm Bean
Sử dụng annotation trong Spring
IoC (Inversion of Control) còn được gọi là Dependency Injection (DI). Đây là quá trình mô tả cách một đối tượng được định nghĩa và các phụ thuộc của nó được xử lý. Các đối tượng phụ thuộc có thể được tiêm thông qua constructor, tham số của factory method, hoặc các thuộc tính. Khi đối tượng được khởi tạo, các phụ thuộc sẽ được tiêm vào - đây là cơ chế "đảo ngược" so với cách truyền thống.
1. Trong Spring, một class được đăng ký làm Bean thông qua annotation
@Component: Annotation này đánh dấu một class là thành phần của Spring, cho phép Spring quản lý và tự động quét class đó.
Khi thêm @Component vào một class nằm trong package được quét bởi @ComponentScan, hoặc định nghĩa @Bean trong configuration class, class đó sẽ được đăng ký vào Spring Container.
@Component
public class ProductService {
}
Hoặc có thể định nghĩa Bean trực tiếp trong class cấu hình:
@Configuration
@ComponentScan("com.example.shop")
public class AppConfig {
@Bean
public ProductService productService() {
return new ProductService();
}
}
2. Khi một Bean cần sử dụng Bean khác, ta cần thực hiện Dependency Injection
@Component
public class OrderService {
private ProductService productService;
@Autowired
public OrderService(ProductService productService) {
this.productService = productService;
}
@Override
public String toString() {
return "OrderService{productService=" + productService + '}';
}
}
Để sử dụng một Bean từ bên trong Bean khác, ta cần sử dụng annotation @Autowired để thực hiện tiêm phụ thuộc tự động.
Các annotation thường dùng
| Annotation | Ý nghĩa |
|---|---|
| @Configuration | Đánh dấu class là class cấu hình |
| @ComponentScan("package") | Chỉ định package cần quét để tìm các annotation |
| @Autowired | Tự động tiêm Bean, có thể đặt trên thuộc tính, phương thức hoặc constructor |
| @Component | Đánh dấu class là Bean, đưa vào container, mặc định là singleton |
| @Bean | Định nghĩa một Bean object, thêm vào Spring Container |
| @Order(số) | Thứ tự ưu tiên khi khởi tạo Bean, số nhỏ hơn có ưu tiên cao hơn |
- Sự khác biệt giữa @Autowired và @Resource?
@Autowired là annotation của Spring, thực hiện tiêm theo kiểu (byType). @Resource là annotation của Java EE (Jakarta EE), thực hiện tiêm theo tên (byName).
Vì @Resource thuộc tiêu chuẩn Java EE, nên nếu sử dụng các IoC container khác không phải Spring, annotation này vẫn tương thích được.
Vậy @Resource dựa trên quy tắc nào để xác định Bean tiêm vào?
Spring cung cấp 4 loại auto-wiring:
byName: Thực hiện khớp theo tên. Ví dụ, nếu class Customer có thuộc tính tên là "paymentProcessor", và trong container có Bean tên là "paymentProcessor", Spring sẽ tự động tiêm Bean đó vào thuộc tính tương ứng.