这里没有说 @ConfigurationProperties 必须设置在控制器或任何其他特定类型的 bean 上,@ConfigurationProperties 实际上经常放在 bean 上。在应用程序中,这些 bean 的惟一目的是作为配置数据的持有者,这使控制器和其他应用程序类不涉及特定于配置的细节,它还使得在几个可能使用该信息的 bean 之间共享公共配置属性变得很容易。
对于 OrderController 中的 pageSize 属性,可以将其提取到一个单独的类中。下面的程序清单以这种方式使用了 OrderProps 类。
程序清单 5.2 提取 pageSize 到持有者类
复制 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 ;
}
正如在 OrderController 中所做的,pageSize 属性默认为 20,同时 OrderProps 使用 @ConfigurationProperties 进行注解,以具有 taco.orders 前缀。
它还带有 @Component 注解,因此 Spring 组件扫描时将自动发现它并在 Spring 应用程序上下文中将其创建为 bean。这很重要,因为下一步是将 OrderProps bean 注入到 OrderController 中。
关于配置属性持有者,没有什么特别的。它们是从 Spring 环境中注入属性的 bean。它们可以被注入到任何需要这些属性的其他 bean 中。对于 OrderController,这意味着从 OrderController 中删除 pageSize 属性,而不是注入并使用 OrderProps bean:
复制 @ Controller
@ RequestMapping ( "/orders" )
@ SessionAttributes ( "order" )
public class OrderController {
private OrderRepository orderRepo;
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" ;
}
...
}
现在 OrderController 不再负责处理它自己的配置属性。这使得 OrderController 中的代码稍微整洁一些,并允许在任何其他需要它们的 bean 中重用 OrderProps 中的属性。此外,正在收集与一个地方的订单相关的配置属性:OrderProps 类。如果需要添加、删除、重命名或以其他方式更改其中的属性,只需要在 OrderProps 中应用这些更改。
例如,假设在其他几个 bean 中使用 pageSize 属性,这时最好对该属性应用一些验证,以将其值限制为不小于 5 和不大于 25。如果没有持有者 bean,将不得不对 OrderController、pageSize 属性以及使用该属性的所有其他类应用验证注解。但是因为已经将 pageSize 提取到 OrderProps 中,所以只需要更改 OrderProps:
复制 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 ;
}
//end::validated[]
尽管可以很容易地将 @Validated、@Min 和 @Max 注解应用到 OrderController(以及可以注入 OrderProps 的任何其他 bean),但这只会使 OrderController 更加混乱。通过使用配置属性持有者 bean,就在在一个地方收集了配置属性的细节,使得需要这些属性的类相对干净。