Nguyên lý Cấu hình Tự động trong Spring Boot

Khi phát triển ứng dụng với Spring Boot, chú thích @SpringBootApplication là điểm khởi đầu quen thuộc. Ít người để ý rằng chú thích này thực chất là một sự kết hợp của ba chú thích quan trọng khác, đóng vai trò nền tảng cho cơ chế cấu hình tự động mạnh mẽ của Spring Boot:

  • @SpringBootConfiguration
  • @EnableAutoConfiguration
  • @ComponentScan

1. @SpringBootConfiguration

Chú thích này đơn giản là một phiên bản đặc biệt của @Configuration. Nó chỉ ra rằng lớp mà nó được áp dụng là một lớp cấu hình chính cho ứng dụng Spring Boot. Điều này có nghĩa là lớp chính của ứng dụng (thường là lớp chứa phương thức main) cũng hoạt động như một nguồn định nghĩa bean và cấu hình.

2. @ComponentScan

@ComponentScan là chú thích chịu trách nhiệm tìm kiếm và đăng ký các thành phần (components) của Spring vào ngữ cảnh ứng dụng. Nó quét các gói được chỉ định để tìm các lớp được đánh dấu bằng các chú thích như @Component, @Service, @Repository, @Controller, và các biến thể khác, sau đó đưa chúng vào Spring IoC container.

Mặc định, @ComponentScan sẽ quét gói chứa lớp @SpringBootApplication và tất cả các gói con của nó. Tuy nhiên, bạn có thể tùy chỉnh phạm vi quét:


// Quét một gói cụ thể
@ComponentScan("com.example.myapp.components")

// Quét nhiều gói
@ComponentScan({"com.example.myapp.services", "com.example.myapp.controllers"})

Để tinh chỉnh quá trình quét, bạn có thể sử dụng thuộc tính excludeFilters hoặc includeFilters. Các bộ lọc này cho phép bạn loại trừ hoặc chỉ định các lớp dựa trên nhiều tiêu chí khác nhau, ví dụ:

  • FilterType.ANNOTATION: Lọc theo chú thích.
  • FilterType.ASSIGNABLE_TYPE: Lọc theo kiểu (class/interface cụ thể).
  • FilterType.ASPECTJ: Lọc bằng biểu thức AspectJ.
  • FilterType.REGEX: Lọc bằng biểu thức chính quy.
  • FilterType.CUSTOM: Lọc bằng quy tắc tùy chỉnh.

Ví dụ, để loại trừ tất cả các lớp được đánh dấu @Controller khỏi quá trình quét trong gói com.example.myapp:


import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.FilterType;
import org.springframework.stereotype.Controller;

@ComponentScan(value = "com.example.myapp", excludeFilters = {
    @ComponentScan.Filter(type = FilterType.ANNOTATION, classes = {Controller.class})
})
public class MyApplication {
    // Các định nghĩa bean khác hoặc phương thức main
}

3. @EnableAutoConfiguration

Đây là chú thích cốt lõi cho phép Spring Boot thực hiện "cấu hình tự động". Nó đóng vai trò bật cơ chế tự động cấu hình, tự động thiết lập các bean và cấu hình dựa trên các thư viện có sẵn trên classpath và cài đặt cấu hình của bạn. Chú thích này bao gồm hai thành phần chính:


@AutoConfigurationPackage
@Import({AutoConfigurationImportSelector.class})

3.1. @AutoConfigurationPackage

Chú thích này đảm bảo rằng Spring Boot biết được gói gốc của ứng dụng. Cụ thể, nó đăng ký gói chứa lớp @SpringBootApplication (và tất cả các gói con của nó) để làm cơ sở cho quá trình quét và tìm kiếm các cấu hình tự động liên quan.

3.2. @Import({AutoConfigurationImportSelector.class})

Thành phần @Import với lớp AutoConfigurationImportSelector là "bộ não" của cấu hình tự động. Nó thực hiện các bước sau để xác định và nạp các cấu hình cần thiết:

  1. Nó quét classpath để tìm kiếm tất cả các tệp META-INF/spring.factories.
  2. Trong các tệp này, nó tìm kiếm các khóa liên quan đến EnableAutoConfiguration, ví dụ: org.springframework.boot.autoconfigure.EnableAutoConfiguration.
  3. Các giá trị của khóa này là danh sách các lớp cấu hình tự động (ví dụ: DataSourceAutoConfiguration, WebMvcAutoConfiguration, v.v.) mà Spring Boot có thể cần áp dụng.
  4. AutoConfigurationImportSelector thu thập danh sách đầy đủ các lớp cấu hình tự động tiềm năng này.
  5. Mặc dù rất nhiều cấu hình tự động được phát hiện, nhưng không phải tất cả đều được áp dụng ngay lập tức. Mỗi lớp cấu hình tự động thường đi kèm với các chú thích điều kiện (@ConditionalOn...) để đảm bảo rằng chúng chỉ được kích hoạt khi các điều kiện cụ thể được thỏa mãn (ví dụ: một class cụ thể có mặt trên classpath, một thuộc tính cấu hình được đặt, v.v.). Điều này cho phép Spring Boot chỉ cấu hình những gì thực sự cần thiết, tránh lãng phí tài nguyên.

Cơ chế Cấu hình Tự động của Spring Boot

Để tóm tắt, quá trình cấu hình tự động của Spring Boot diễn ra như sau:

  1. Phát hiện các cấu hình: Spring Boot tìm kiếm tất cả các lớp *AutoConfiguration có sẵn trên classpath thông qua cơ chế META-INF/spring.factories.
  2. Đánh giá điều kiện: Mỗi lớp *AutoConfiguration được kiểm tra dựa trên các điều kiện của nó (sử dụng @Conditional). Chỉ những cấu hình thỏa mãn điều kiện mới được kích hoạt.
  3. Liên kết thuộc tính: Các cấu hình được kích hoạt thường liên kết với các đối tượng *Properties (ví dụ: ServerProperties cho cấu hình server web), các đối tượng này lấy giá trị từ tệp cấu hình ứng dụng của bạn (như application.properties hoặc application.yml).
  4. Đăng ký Bean: Dựa trên các thuộc tính đã liên kết và các điều kiện đã thỏa mãn, các lớp *AutoConfiguration sẽ tự động đăng ký các bean cần thiết vào Spring IoC container, cung cấp các tính năng sẵn sàng để sử dụng (ví dụ: một máy chủ web nhúng, một DataSource, một EntityManager, v.v.).
  5. Tùy chỉnh:
    • Người dùng có thể ghi đè các bean được cung cấp bởi cấu hình tự động bằng cách định nghĩa một bean cùng tên (hoặc cùng kiểu nếu bean tự động cấu hình cho phép ghi đè) trong lớp cấu hình của riêng mình (sử dụng @Bean).
    • Người dùng có thể tùy chỉnh hành vi của các thành phần tự động cấu hình bằng cách thay đổi các giá trị thuộc tính trong tệp application.properties hoặc application.yml.

Sơ đồ đơn giản hóa của luồng này:

*AutoConfiguration → Tạo/Định nghĩa Component → Lấy giá trị từ *Properties → Tùy chỉnh qua application.properties

Để tìm hiểu chi tiết về các thuộc tính cấu hình có sẵn và cách tùy chỉnh chúng, bạn có thể tham khảo tài liệu chính thức của Spring Boot:

https://docs.spring.io/spring-boot/docs/current/reference/html/appendix-application-properties.html#common-application-properties

Thẻ: Spring Boot auto-configuration Dependency Injection Component Scanning META-INF/spring.factories

Đăng vào ngày 10 tháng 8 lúc 17:13