@ConditionalOn* Family Và Thứ Tự Nạp Bean Autoconfig
Tìm hiểu 12 annotation @ConditionalOn*, cơ chế back-off nhường bean của @ConditionalOnMissingBean và cách sắp xếp thứ tự nạp bằng DAG topological sort.
TL;DR: @ConditionalOn* là tập hợp các bộ lọc điều kiện đảm bảo các lớp cấu hình tự động chỉ đăng ký bean khi thỏa mãn toàn bộ yêu cầu về môi trường runtime. Trong đó, @ConditionalOnMissingBean đóng vai trò trung tâm trong mô hình Back-Off: Spring Boot chỉ tạo bean mặc định khi lập trình viên chưa tự định nghĩa bean cùng loại. Các annotation @AutoConfigureBefore và @AutoConfigureAfter thiết lập đồ thị có hướng (DAG) để sắp xếp thứ tự thẩm định, ngăn ngừa lỗi tranh chấp định nghĩa bean. Khi gặp sự cố nạp bean, Actuator endpoint /actuator/conditions là công cụ chẩn đoán chính xác nhất.
Làm chủ họ annotation này và nguyên lý sắp xếp thứ tự giúp bạn loại bỏ hoàn toàn các lỗi xung đột bean vô hình khi xây dựng hệ thống phức tạp.
1. Vì sao Auto-configuration bắt buộc phải có điều kiện kích hoạt?
Nếu Spring Boot tự động nạp toàn bộ các bean mà không kiểm tra điều kiện, xung đột bean sẽ xảy ra liên tục:
// Gia su khong co dieu kien can thiep
@AutoConfiguration
public class CacheAutoConfiguration {
@Bean
public CacheManager cacheManager() {
return new ConcurrentMapCacheManager(); // Luon tao mac dinh
}
}
Khi dự án của bạn muốn chuyển sang Redis và tự định nghĩa một RedisCacheManager, container sẽ cùng lúc có 2 bean CacheManager, dẫn tới lỗi NoUniqueBeanDefinitionException ngay lúc khởi động. Do đó, mọi bean cấu hình sẵn của Spring Boot đều bắt buộc phải đi kèm điều kiện thẩm định.
2. Họ 12 annotation @ConditionalOn* giải quyết những bài toán nào?
Spring Boot cung cấp sẵn 12 annotation chuyên biệt để truy vấn trạng thái môi trường:
| Annotation | Câu hỏi thẩm định môi trường | Trường hợp sử dụng tiêu biểu |
|---|---|---|
@ConditionalOnClass | Class chỉ định có mặt trên classpath không? | Kích hoạt cấu hình khi người dùng thêm starter |
@ConditionalOnMissingClass | Class chỉ định vắng mặt trên classpath? | Cung cấp phương án thay thế khi thiếu driver |
@ConditionalOnBean | Bean kiểu chỉ định đã được đăng ký chưa? | Tạo bean phụ thuộc vào một bean khác |
@ConditionalOnMissingBean | Bean kiểu chỉ định chưa hề tồn tại? | Tạo bean mặc định nhường quyền cho người dùng |
@ConditionalOnProperty | Thuộc tính cấu hình có giá trị khớp không? | Bật tắt tính năng bằng Feature Flag |
@ConditionalOnWebApplication | Ứng dụng có đang chạy môi trường Web không? | Khai báo các Controller và Servlet Filter |
Khi gắn nhiều annotation điều kiện trên cùng một lớp hoặc phương thức, Spring áp dụng quy tắc AND: tất cả điều kiện đều phải thỏa mãn thì bean mới được đăng ký.
3. Cơ chế Back-Off của @ConditionalOnMissingBean vận hành ra sao?
@ConditionalOnMissingBean là nền tảng giúp Spring Boot duy trì tính linh hoạt "Opinionated but not lock-in":
@AutoConfiguration
public class CacheAutoConfiguration {
@Bean
@ConditionalOnMissingBean // Chi tao neu nguoi dung CHUA tu khai bao
public CacheManager cacheManager() {
return new ConcurrentMapCacheManager();
}
}
Khi bạn khai báo một bean CacheManager của riêng mình trong mã nguồn, Spring Boot nhận diện bean đã tồn tại và tự động rút lui.

So với việc dùng exclude để loại bỏ cả class cấu hình, cơ chế back-off ưu việt hơn vì nó chỉ ghi đè đúng bean mục tiêu mà vẫn giữ lại toàn bộ các thiết lập phụ trợ (như properties binding và cache listener).
4. Tại sao thứ tự nạp qua @AutoConfigureBefore và After lại quan trọng?
Vì @ConditionalOnMissingBean phụ thuộc hoàn toàn vào trạng thái hiện tại của container, thứ tự thẩm định giữa các autoconfig mang tính sống còn:

Nếu autoconfig B chạy trước A, B thấy chưa có bean và tự tạo; sau đó A chạy mà không có điều kiện sẽ cố tạo thêm bean nữa, làm nổ lỗi BeanDefinitionOverrideException.
Để xử lý, Spring Boot cung cấp các chỉ dẫn thứ tự:
@AutoConfiguration(after = DataSourceAutoConfiguration.class)
public class HibernateJpaAutoConfiguration { /* ... */ }
@AutoConfiguration(after = HibernateJpaAutoConfiguration.class)
public class JpaRepositoriesAutoConfiguration { /* ... */ }
5. Thuật toán sắp xếp thứ tự AutoConfigurationSorter xử lý DAG thế nào?
Spring Boot không chạy cấu hình tuần tự theo danh sách ngẫu nhiên. Lớp AutoConfigurationSorter thực hiện các bước sau:
- Thu thập toàn bộ các quan hệ phụ thuộc từ
@AutoConfigureBeforevà@AutoConfigureAfter. - Xây dựng một đồ thị có hướng không chu trình (DAG - Directed Acyclic Graph).
- Áp dụng thuật toán Topological Sort để tạo ra một chuỗi thực thi tuyến tính an toàn tuyệt đối.
Nếu xuất hiện phụ thuộc vòng tròn (A after B, B after A), Spring Boot sẽ lập tức báo lỗi IllegalStateException khi khởi động.
6. Làm thế nào để điều tra lỗi nạp Bean bằng Actuator /conditions?
Khi một bean không được nạp như mong đợi, hãy kích hoạt endpoint Actuator:
management:
endpoints:
web:
exposure:
include: conditions
Truy cập GET /actuator/conditions trả về cấu trúc chi tiết:
positiveMatches: Danh sách cấu hình đã nạp thành công kèm lý do pass.negativeMatches: Danh sách cấu hình bị bỏ qua kèm nguyên nhân cụ thể (ví dụ: thiếu class hoặc thiếu property).exclusions: Danh sách các cấu hình bị loại trừ thủ công quaexclude.
Khi phát triển cục bộ, bạn có thể truyền cờ --debug khi chạy ứng dụng để Spring Boot in toàn bộ bảng kiểm tra này ra màn hình console.
7. Những cạm bẫy thứ tự phổ biến khi cấu hình điều kiện?
- Quên @ConditionalOnMissingBean trên bean mặc định: Dẫn đến việc khi người dùng tự khai báo bean, container bị trùng lặp bean.
- Đặt @AutoConfigureAfter trên class @Configuration thông thường: Annotation này hoàn toàn vô tác dụng trên các class cấu hình của ứng dụng; nó chỉ có hiệu lực trên các class gắn
@AutoConfigurationnạp qua file imports.
Tóm tắt
@ConditionalOn*bảo vệ hệ thống khỏi xung đột bean bằng cách thẩm định môi trường runtime theo quy tắc AND.@ConditionalOnMissingBeanhiện thực hóa cơ chế back-off, cho phép lập trình viên ghi đè cấu hình mặc định một cách tự nhiên.- Thứ tự thẩm định quyết định kết quả của các điều kiện phụ thuộc; được kiểm soát qua
@AutoConfigureBeforevà@AutoConfigureAfter. AutoConfigurationSortersử dụng thuật toán Topological Sort trên đồ thị DAG để loại bỏ phụ thuộc vòng tròn.- Sử dụng
/actuator/conditionsđể đọc báo cáoConditionEvaluationReportthay vì đoán mò khi gỡ lỗi.
Tự kiểm tra
- Q1Cơ chế Back-Off trong Spring Boot Auto-configuration hoạt động như thế nào?
- Q2Tại sao việc ghi đè bean qua cơ chế Back-Off lại được khuyến nghị hơn việc loại trừ hoàn toàn bằng exclude trên @SpringBootApplication?
- Q3Lớp AutoConfigurationSorter của Spring Boot sử dụng cấu trúc dữ liệu và giải thuật nào để sắp xếp thứ tự nạp các lớp cấu hình tự động?
- Q4Annotation @AutoConfigureAfter chỉ có hiệu lực khi được đặt trên loại lớp nào?
- Q5Khi một bean autoconfig không được tạo như kỳ vọng, bạn nên tra cứu mục nào trong phản hồi của endpoint /actuator/conditions để tìm nguyên nhân?
Bài tiếp theo: Mini-Challenge: Trace 1 Request Qua Từng Layer
Bài này có giúp bạn hiểu bản chất không?
Bài này đáng gửi cho bạn học cùng?
Copy link đã gắn nguồn — dán group, chat, hoặc LinkedIn.
@EnableAutoConfiguration: Cơ Chế Đọc File Imports
Bài tiếpMini-Challenge: Trace 1 Request Và Thứ Tự Khởi Tạo Bean
Lộ trình Junior Java Backend Developer
Chặng 14/21 · Spring Boot & autoconfiguration — bài 6/16 của chặng
Ôn phỏng vấn
Bài này trả lời được các câu phỏng vấn sau — tự trả lời thử trước khi mở đáp án.
Thảo luận & góp ý
Hỏi đáp về bài này