Skip to content

6.2.1 Định nghĩa các bean giữ cấu hình

Không có gì bắt buộc rằng @ConfigurationProperties phải được đặt trên controller hay bất kỳ loại bean cụ thể nào khác. Trên thực tế, @ConfigurationProperties thường được đặt trên các bean chỉ phục vụ mục đích duy nhất trong ứng dụng là giữ dữ liệu cấu hình. Điều này giúp giữ cho các chi tiết cấu hình không bị lẫn vào các controller hoặc các lớp ứng dụng khác. Nó cũng giúp việc chia sẻ các thuộc tính cấu hình chung giữa nhiều bean trở nên dễ dàng nếu các bean đó cần sử dụng thông tin đó.

Trong trường hợp thuộc tính pageSize trong OrderController, bạn có thể tách nó ra thành một lớp riêng biệt. Đoạn mã sau sử dụng lớp OrderProps theo cách như vậy.

Danh sách 6.2 Tách pageSize thành một lớp giữ giá trị

java
package tacos.web;
import org.springframework.boot.context.properties.
                    ConfigurationProperties;
import org.springframework.stereotype.Component;
import lombok.Data;

@Component
@ConfigurationProperties(prefix="taco.orders")
@Data
public class OrderProps {

  private int pageSize = 20;

}

Cũng như bạn đã làm với OrderController, thuộc tính pageSize mặc định là 20, và OrderProps được chú thích với @ConfigurationProperties với tiền tố là taco.orders. Nó cũng được chú thích với @Component để Spring có thể tự động quét và tạo ra bean trong ngữ cảnh ứng dụng của Spring. Điều này rất quan trọng, vì bước tiếp theo là tiêm (inject) bean OrderProps vào OrderController.

Không có điều gì đặc biệt đối với các bean giữ cấu hình. Chúng là các bean có các thuộc tính được tiêm từ môi trường của Spring. Chúng có thể được tiêm vào bất kỳ bean nào khác cần các thuộc tính đó. Đối với OrderController, điều này có nghĩa là bạn sẽ loại bỏ thuộc tính pageSize khỏi OrderController và thay vào đó sử dụng bean OrderProps được tiêm vào, như sau:

java
private OrderProps props;

public OrderController(OrderRepository orderRepo,
          OrderProps props) {
  this.orderRepo = orderRepo;
  this.props = props;
}

...

@GetMapping
public String ordersForUser(
      @AuthenticationPrincipal User user, Model model) {

  Pageable pageable = PageRequest.of(0, props.getPageSize());
  model.addAttribute("orders",
      orderRepo.findByUserOrderByPlacedAtDesc(user, pageable));

  return "orderList";
}

Giờ đây, OrderController không còn chịu trách nhiệm quản lý các thuộc tính cấu hình của riêng nó nữa. Điều này làm cho mã trong OrderController gọn gàng hơn một chút và cho phép bạn tái sử dụng các thuộc tính trong OrderProps trong bất kỳ bean nào khác cần đến chúng. Hơn nữa, bạn đang gom tất cả các thuộc tính cấu hình liên quan đến đơn hàng vào một nơi: lớp OrderProps. Nếu bạn cần thêm, xóa, đổi tên hoặc thay đổi thuộc tính nào đó, bạn chỉ cần áp dụng những thay đổi đó trong OrderProps. Và khi kiểm thử, bạn có thể dễ dàng thiết lập các thuộc tính cấu hình trực tiếp trên một phiên bản OrderProps dành riêng cho test và truyền nó vào controller trước khi chạy test.

Ví dụ, giả sử bạn đang sử dụng thuộc tính pageSize trong nhiều bean khác nhau và quyết định rằng sẽ tốt hơn nếu áp dụng một số ràng buộc kiểm tra cho thuộc tính đó để giới hạn giá trị tối thiểu là 5 và tối đa là 25. Nếu không có một bean giữ cấu hình, bạn sẽ phải áp dụng các annotation kiểm tra vào OrderController, thuộc tính pageSize, và tất cả các lớp khác sử dụng thuộc tính đó. Nhưng vì bạn đã tách pageSize ra thành OrderProps, bạn chỉ cần thực hiện các thay đổi đối với OrderProps, như sau:

java
package tacos.web;
import javax.validation.constraints.Max;
import javax.validation.constraints.Min;

import org.springframework.boot.context.properties.
                ConfigurationProperties;
import org.springframework.stereotype.Component;
import org.springframework.validation.annotation.Validated;

import lombok.Data;

@Component
@ConfigurationProperties(prefix="taco.orders")
@Data
@Validated
public class OrderProps {

  @Min(value=5, message="must be between 5 and 25")
  @Max(value=25, message="must be between 5 and 25")
  private int pageSize = 20;

}

Mặc dù bạn cũng có thể dễ dàng áp dụng các annotation @Validated, @Min@Max vào OrderController (và bất kỳ bean nào khác được tiêm với OrderProps), điều đó sẽ khiến OrderController trở nên rối rắm hơn. Với một bean giữ cấu hình, bạn đã gom tất cả thông tin cấu hình vào một nơi, giữ cho các lớp cần dùng các thuộc tính đó trở nên sạch sẽ hơn.

Released under the MIT License.