java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > 实体类使用@Builder导致@ConfigurationProperties注入属性失败

实体类使用@Builder,导致@ConfigurationProperties注入属性失败问题

作者:搏·梦

这篇文章主要介绍了实体类使用@Builder,导致@ConfigurationProperties注入属性失败问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教

1. 前言

这里只是列出,可能需要补一下的知识点:

具体的yml文件字符串、List、Map的书写方式并使用@ConfigurationProperties注入配置类.

使用@Builder导致的无法创建无参构造方法

2. 场景

@ConfigurationProperties注入属性,有两个很重要的条件:

偶然一次发现,当在该类加上@Builder注解,会直接导致无法属性注入。

重现

正常情况下:

@ToString
@Setter
@Component
@ConfigurationProperties(prefix = "failed.test")
public class demoFailedTest {

    private String username;
    private int age;
    private demoPerson demoPerson;
}

@Setter
@ToString
public class demoPerson {
    private String name;
    private String sex;
}
@Component("demoFailedTestRunner")
public class demoRunner implements ApplicationRunner {

    @Autowired
    demoFailedTest demoFailedTest;

    @Override
    public void run(ApplicationArguments args) throws Exception {
        System.out.println(demoFailedTest);
    }
}

failed:
  test:
    user-name: failedTest
    age: 19
    demo-person:
      name: person
      sex: boy

异常情况:当在demoPerson类上加上@Builder注解:

@Builder
@Setter
@ToString
public class demoPerson {
    private String name;
    private String sex;
}

一开始都惊了,本来就是符合条件的,demoPerson类上面有set方法,不应该注入不进来。

3. 解释

1.上面两张图片有个输出有个很细微的差异,一开始我也没有看出来,后来才反应过来了:

第一个:

demoFailedTest(username=failedTest, age=19, demoPerson=demoPerson(name=person, sex=boy))

第二个:

demoFailedTest(username=failedTest, age=19, demoPerson=null)

注: demoPerson类上 加了@ToString

讲道理,第二个报错不应该是:

demoFailedTest(username=failedTest, age=19, demoPerson=demoPerson(name=null, sex=null))

这样子才是真正注入不进来属性的结果。

那么现在直接 demoPerson=null 代表 该demoPerson根本没有被创建对象!!!

2.后来详细去了解了@Builder注解的作用:

详细:使用@Builder导致的无法创建无参构造方法

简单说一下:就是如果你只是使用了@Builder则会导致 该类的没有无参构造函数,会有全参构造函数

3.重点:spring属性注入的时候,为什么要有set方法,显示它是使用set方法注入的,它又不能直接使用对象.set方法(),想必是使用了反射,那就必须得有对象吧,可得 spring肯定是先反射创建对象,是的,没错,spring默认是使用无参构造函数创建对象,再调用反射的set方法。

4.因此,如果加上@Builder注解,会没有无参构造函数方法,当然是没有办法创建对象了,因此才会出现 demoPerson=null的结果

4. 解决方法

具体@Builder的解决方法,上面链接里面有三种,我演示其中一种,即在该类上加上@AllArgsConstructor@NoArgsConstructor。

@ToString
@Setter
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class demoPerson {
    private String name;
    private String sex;

}

5. 思考

根据第四大点的解决方法,加上@AllArgsConstructor、@NoArgsConstructor即可,但有没有想过为什么要用@Builder方法

原因:

如果要满足第二点原因,显然现在是无法做到的,因为spring使用set方法注入,得有无参构造方法先创建对象,但是我们又不想提供无参构造方法,这不是矛盾吗?

再额外补充一个问题:如果这个Person类,我只想通过配置文件注入之后,永远不被修改,固然不能提供set方法,但是因为spring使用set方法注入属性,这不也是矛盾吗?

此时,突然脑子里面肯定会出现一个想法:为什么只会有set方法注入,不应该吧,set都可以,应该也可以有构造函数注入吧。

是的,下一篇文章:

spring的构造函数注入属性@ConstructorBinding 

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

您可能感兴趣的文章:
阅读全文