Spring Boot bài 03: Bean, IoC và Dependency Injection qua constructor
- 18-10-2026
- Toanngo92
- 0 Comments
Giáo trình Spring Boot MVC và REST API · Chương 2/12: Bean, kiến trúc và cấu hình · Bài 03/28 · Biên soạn tháng 10/2026.
Mục lục
Mục tiêu bài học
Hiểu Spring tạo và nối các đối tượng thế nào; biết chọn constructor injection và phân biệt đối tượng do Spring quản lý.
Vấn đề khi tự tạo mọi đối tượng
Một Controller cần CourseService, còn CourseService cần CourseRepository và CategoryRepository. Nếu Controller tự dùng new để tạo toàn bộ chuỗi này, nó phải biết cả cấu hình dữ liệu và cách khởi tạo các phụ thuộc. Thay cách lưu dữ liệu hoặc viết test trở nên khó hơn vì các đối tượng bị gắn chặt với nhau.
IoC là việc chuyển quyền tạo và quản lý các thành phần phù hợp cho container. Bean là đối tượng được Spring quản lý trong container đó. Dependency Injection là cách Spring cung cấp phụ thuộc cho đối tượng, thay vì đối tượng tự tìm hoặc tự tạo chúng. Đây là cơ chế tổ chức chương trình, không phải phép thuật thay thế thiết kế.
Tệp trong mã nguồn mẫu: src/main/java/com/hocvietcode/academy/CourseService.java. Đoạn dưới được trích từ tệp này; xem bản tải về để có đủ import và phần còn lại.
@Service @Transactional(readOnly=true)
public class CourseService {
private final CourseRepository courses; private final CategoryRepository categories;
public CourseService(CourseRepository courses,CategoryRepository categories){this.courses=courses;this.categories=categories;}
Vì sao tiêm qua constructor?
CourseService khai báo hai trường final và nhận đủ phụ thuộc qua constructor. Nếu thiếu repository, việc tạo service thất bại sớm thay vì chờ đến một request rồi mới gặp null. Với một constructor, không cần ghi thêm @Autowired. Trong unit test, ta có thể truyền mock repository mà không khởi động Spring.
@Service được component scan phát hiện. Repository là interface, nhưng Spring Data cung cấp implementation khi khởi động dựa vào JpaRepository. Không cần tự viết class CourseRepositoryImpl cho CRUD có sẵn. Controller nhận CourseService theo cùng nguyên tắc, nên tuyến phụ thuộc đi từ web xuống nghiệp vụ rồi đến dữ liệu.
Khi nào dùng @Bean?
Với class do mình viết, @Service hoặc @Component thường đủ. Với đối tượng của thư viện hoặc đối tượng cần lắp ráp theo cấu hình, đặt một phương thức @Bean trong @Configuration. AppConfig tạo RestClient từ builder, địa chỉ gốc và timeout. SecurityConfig tạo PasswordEncoder và SecurityFilterChain bằng cách này.
Điểm cần nhớ là gọi new cho một đối tượng thuần Java không tự động làm nó trở thành bean. Nếu tự new CourseService bên ngoài Spring, các hành vi dựa trên proxy như @Transactional cũng không tự hoạt động. Ta vẫn dùng new bình thường cho DTO, entity hoặc giá trị không cần vòng đời của container.
Vòng đời và trạng thái dùng chung
Mặc định, phần lớn bean là singleton trong một application context. Điều đó không có nghĩa chỉ có một đối tượng cho mọi chương trình trên máy; nó có nghĩa một instance được các request trong context dùng chung. Vì vậy không đặt currentUser, danh sách khóa học đang sửa hay dữ liệu riêng của request vào trường mutable của Service.
Các biến cục bộ của phương thức giúp tách dữ liệu theo lần gọi. Trạng thái nghiệp vụ cần lưu vào cơ sở dữ liệu, còn thông tin đăng nhập do hệ thống Security quản lý. Nếu hai service phụ thuộc vòng vào nhau, hãy xem lại trách nhiệm và hướng gọi trước khi tìm cách bật circular references.
Đọc lỗi khởi động theo quan hệ phụ thuộc
Thông báo No qualifying bean thường cho biết chưa có bean phù hợp: thiếu annotation, class nằm ngoài package scan hoặc cấu hình không được nạp. Nếu có hai bean cùng kiểu, Spring cần biết chọn bean nào qua @Qualifier hoặc @Primary. Hãy đọc phần nguyên nhân cuối của stack trace để tìm mắt xích thực sự bị lỗi.
Lỗi thường gặp và lưu ý
- Không dùng field của singleton bean để lưu thông tin riêng của người đang truy cập.
- Không thêm @Autowired vào mọi nơi như một cách chữa lỗi thiếu dependency; hãy kiểm tra bean có được tạo đúng không.
Ghi nhớ
Constructor thể hiện rõ mỗi class cần gì. Container chịu trách nhiệm nối phụ thuộc, còn class tập trung làm đúng công việc của nó.

