当前位置:   article > 正文

springboot属性注入方式_springboot枚举怎么才能注入

springboot枚举怎么才能注入

springboot属性注入方式

在spring中我们要读取一个配置文件中的属性通常会使用@Value来注入对应的属性值,但@Value一次性只能注入一个属性值,不太方便统一管理。由此springboot中提供了一个可通过前缀分组的的注解对同一特征的属性统一管理。这就是@ConfigurationProperties

  1. @Target({ElementType.TYPE, ElementType.METHOD})
  2. @Retention(RetentionPolicy.RUNTIME)
  3. @Documented
  4. public @interface ConfigurationProperties {
  5. @AliasFor("prefix")
  6. String value() default "";
  7. @AliasFor("value")
  8. String prefix() default "";
  9. boolean ignoreInvalidFields() default false;
  10. boolean ignoreUnknownFields() default true;
  11. }

可以看到@ConfigurationProperties中的属性并不多:

  • prefix:配置文件中属性的前缀。通过这个前缀类标识需要匹配该前缀下的属性
  • ignoreInvalidFields:是否忽略无法转换的属性
  • ignoreUnknownFields:是否忽略未知的属性值

@ConfigurationProperties通常用以标识一个属性配置类,其本身只是一个标识,读取配置文件并提取注入对应值的过程则在spring的生命周期中-【准确的说是通过BeanPostProcessor,InitializingBean。这里不做详细描述,感兴趣的胖友可以自己挖坑】完成,所以要想使用@ConfigurationProperties所标识的属性配置类还需要将对应的类注入到spring容器中。由此我们得出springboot属性注入的两个步骤:

  • @ConfigurationProperties标识我们需要映射哪个prefix下的属性值
  • 将 @ConfigurationProperties标识的类注入到spring容器中

springboot属性注入的几种方式

为了测试不同注入方式的效果,我们首先创建一个application.yml文件,它就是属性配置文件:

  1. user:
  2. user-name: kell
  3. password: 888888
  4. email: kell@qq.com
  5. sex: man
  6. phone: 18345678900

为了后面我们需要测试一波,我们在创建一个Application类和一个测试类:

  1. @SpringBootApplication
  2. public class PropApplication {
  3. public static void main(String[] args) {
  4. SpringApplication.run(PropApplication.class,args);
  5. }
  6. }
  1. @Slf4j
  2. public class UserService {
  3. private UserProperties userProperties;
  4. public UserService(UserProperties userProperties) {
  5. this.userProperties = userProperties;
  6. }
  7. public void getUser(){
  8. if(userProperties==null){
  9. log.info("[user properties is null]");
  10. return;
  11. }
  12. log.info("[user info:userName:{}]",userProperties.getUserName());
  13. }
  14. }
  1. @RunWith(SpringJUnit4ClassRunner.class)
  2. @SpringBootTest(classes = PropApplication.class)
  3. public class PropTest {
  4. @Resource
  5. private UserService userService;
  6. @Test
  7. public void test_getUser(){
  8. userService.getUser();
  9. }
  10. }

通过@Component注入

  1. @Component
  2. @ConfigurationProperties(prefix = "user")
  3. public class UserProperties {
  4. private String userName;
  5. private String password;
  6. private String email;
  7. private String sex;
  8. private String phone;
  9. //省略get,set方法
  10. }

使用@Component注解直接将属性配置类注入到spring中。

这种方式是最简单,但是不提倡这样使用。通常情况下我们可能会将项目中的所有配置类都放在一起,可能是通过依赖包的形式,这个时候我们配置spring扫描的时候,可能并不会扫描到这些路径,这就会导致@Component不起作用。

通过@Bean注入

  1. @ConfigurationProperties(prefix = "user")
  2. public class UserProperties {
  3. private String userName;
  4. private String password;
  5. private String email;
  6. private String sex;
  7. private String phone;
  8. //省略get,set方法
  9. }
  1. @Configuration
  2. public class PropConfig {
  3. @Bean
  4. public UserProperties userProperties(){
  5. return new UserProperties();
  6. }
  7. @Bean
  8. public UserService userService(){
  9. return new UserService(this.userProperties());
  10. }
  11. }

这是一种可选的方式,但是不够简练需要new一个配置类然后再注入

通过@EnableConfigurationProperties注入

  1. @ConfigurationProperties(prefix = "user")
  2. public class UserProperties {
  3. private String userName;
  4. private String password;
  5. private String email;
  6. private String sex;
  7. private String phone;
  8. //省略get,set方法
  9. }
  1. @Configuration
  2. @EnableConfigurationProperties(UserProperties.class)
  3. public class PropConfig {
  4. @Bean
  5. public UserService userService(UserProperties userProperties){
  6. return new UserService(userProperties);
  7. }
  8. }

使用@EnableConfigurationProperties和使用@Component的区别在于:
@EnableConfigurationProperties能够将属性类的定义和使用区分开。属性类可能在其他项目中定义,只要在使用到该类的地方使用@EnableConfigurationProperties开启某个配置,该配置类即可以被注入到spring中。
这也是最为提倡的方式,springboot自动配置实现中就是采用这种方式。

springboot属性注入其他特性

宽松绑定

  1. user-name : kell
  2. user_name: kell
  3. USER_NAME: kell
  4. userName:kell
  5. UserName:kell

Spring使用一些宽松的绑定属性规则。因此,以上变体都将绑定到userName属性上。

复杂属性类型

List 和 Set

如果我们想给user添加一个集合类型的属性(如:一个user他有多本书籍),该怎么办呢?
这里有两种写法:

  1. user:
  2. user-name: kell
  3. books[0]: 书名1
  4. books[1]: 书名2
  1. user:
  2. user-name: kell
  3. books:
  4. - 书名1
  5. - 书名2

运行结果:

自定义类型

如果我们想给user定义一个体重的属性,这个属性是带有单位的,那我们怎么自动解析对应的值呢?如下

  1. user:
  2. user-name: kell
  3. books[0]: 书名1
  4. books[1]: 书名2
  5. weight: 60KG

当然你可以直接通过字符串接受对应值。除此之外我们还可以通过Converter集中处理那些属性。

  1. public class Weight {
  2. private Double weight;
  3. private String unit;
  4. public Weight(Double weight, String unit) {
  5. this.weight = weight;
  6. this.unit = unit;
  7. }
  8. //省略get,set方法
  9. }

我们定义了一个weight的类,这个类包含重量和单位。

  1. public enum WeightUnitEnum {
  2. KG(1),
  3. TON(2);
  4. private int unit;
  5. WeightUnitEnum(int unit) {
  6. this.unit = unit;
  7. }
  8. public int getUnit() {
  9. return unit;
  10. }
  11. public void setUnit(int unit) {
  12. this.unit = unit;
  13. }
  14. //将字符串转化为weight
  15. public static Weight getWeight(String weightStr){
  16. Weight weight=new Weight(0D,KG.name());
  17. if(StringUtils.isEmpty(weightStr)){
  18. return weight;
  19. }
  20. for(WeightUnitEnum weightUnit:WeightUnitEnum.values()){
  21. if(weightStr.endsWith(weightUnit.name())){
  22. double weightNum=Double.parseDouble(weightStr.substring(0,weightStr.indexOf(weightUnit.name())));
  23. weight.setUnit(weightUnit.name());
  24. weight.setWeight(weightNum);
  25. }
  26. }
  27. return weight;
  28. }
  29. }

我们定义了一个枚举,这个枚举中定义类单位。并且里面新增了一个将字符解析为weight的方法。

  1. public class WeightConverter implements Converter<String, Weight> {
  2. @Override
  3. public Weight convert(String s) {
  4. return WeightUnitEnum.getWeight(s);
  5. }
  6. }

通过实现Converter,我们定义了一个自动解析转化属性类型的方法。为了使该方法起作用,我们还需要将他注入到spring容器中:

  1. @Configuration
  2. @EnableConfigurationProperties(UserProperties.class)
  3. public class PropConfig {
  4. @Bean
  5. public UserService userService(UserProperties userProperties){
  6. return new UserService(userProperties);
  7. }
  8. //注入属性转化器
  9. @Bean
  10. @ConfigurationPropertiesBinding
  11. public WeightConverter weightConverter(){
  12. return new WeightConverter();
  13. }
  14. }

运行结果:

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小丑西瓜9/article/detail/388449
推荐阅读
相关标签
  

闽ICP备14008679号