当前位置:职场发展 > 使用Lombok @AllArgsConstructor注解和@Value注解带来的问题以及对Spring的一些思考

使用Lombok @AllArgsConstructor注解和@Value注解带来的问题以及对Spring的一些思考

  • 发布:2023-10-01 20:13

背景

昨天同事导出excel的时候,有一栏是空的,就问我怎么回事。我查看了一下,发现数据库中这个字段没有任何值。后来想想,可能当时的设计有问题,所以这个列的值就没有设置。这个值是固定的,不会改变。因此,数据库使用字段来存储固定值。其实是设计有问题。假设存储了十万行数据,那么这个值也将保持不变。 ,没有意义,而且浪费资源,所以我把这个固定值放到了springBoot的yml文件中,然后导出数据的时候,直接从yml中获取这个值并填写即可。暂时我直接使用@Value注解来获取这个值,但是启动时就报错。看了代码,好像没有什么问题(也许是我的错)。

伪代码

以下是伪代码。不难看出下面使用了Lombok的@AllArgsConstructor,所以Spring会使用该构造函数来组装Bean。

@RestController
@AllArgsConstructor
publicclassTestController{

@值( "${www.sychzs.cn}")
private String appName;

private 测试服务 testService;

@GetMapping("/exportExcel")
publicvoidexportExcel(@Valid ServiceEvaluateVO serviceEvaluateVO,HttpServletResponse响应) {
//省略部分代码
}
}

上面我想通过@Value注解获取yml配置信息,但是项目启动并报错,如下;

构造函数in io.steakliu.spring.boot.controller.TestController 的参数 0 需要类型 ' java.lang。找不到字符串'

可以看出Spring找不到'java.lang.String'类型的bean。事实上,它找不到appName。因为使用了@AllArgsConstructor,所以spring实例化构造函数的时候会组装所有的属性。 ,所以找不到appName。

解决方案

这个问题很容易解决。在解决这个问题之前,我们需要知道@Value发生在哪个阶段。 @Value发生在属性填充阶段。将上面的appName添加到构造函数中,并使用Lombok。 @AllArgsConstructor,所以在这个阶段一定找不到appName。

手动创建构造函数

如果不使用@AllArgsConstructor,而是自己创建构造函数,则可以稍作修改,为appName赋值,如下:

@RestController
public class TestController {
    私有  字符串appName;
    私有 TestService testService;

    public TestController(@Value("${www.sychzs.cn}") String appName, TestService testService ){
        这个.appName = appName;
        这个.testService = testService ;
    }

    @GetMapping ("/exportExcel")
    public void exportExcel (@Valid ServiceEvaluateVO serviceEvaluateVO,HttpServletResponse 响应){
        //省略若干代码
    }
}

上面手动创建构造函数,然后在appName前面加上@Value注解,那么appName就可以进行属性填充,不过,这样有一个问题,那就是需要手动创建构造函数,如果要注入的bean很多,构造函数就会变得很庞大,所以使用@AllArgsConstructor可以让代码变得整洁,但是遇到我这种傻逼非要在这里使用@Value,那么不好就办了。

单独写一个类

当然,我们也可以直接将它写入一个类中,这样直接在别处注入就可以,扩展性也好。

@Component
@Data
public class AppInfo {

@值( "${www.sychzs.cn}")
private String appName;
}

如下,直接注入AppInfo bean,然后就不需要手动创建构造函数了。您可以放心使用@AllArgsConstructor。

@RestController
@AllArgsConstructor
publicclassTestController{
私人AppInfo appInfo; | public voidexportExcel(@Valid ServiceEvaluateVO serviceEvaluateVO,HttpServletResponse响应){
   //省略一些代码
       }
}

不使用构造函数注入

当然,你也可以不使用构造函数来注入bean。您可以使用@Autowired和@Resource来注入bean。这没有问题。这样,所有的属性都会在属性填充阶段被赋值,就不会出现找不到的问题。属性。

```java
@RestController
publicTestController{
  @值( ? private TestService testService;

@GetMapping("/exportExcel") 公共 无效 exportExcel(@Valid ServiceEvaluateVO serviceEvaluateVO , HttpServletResponse 响应) {
//省略一些代码
}
}

总结

其实这个问题很简单,也很容易排查。这样的错误不应该发生。其实归根结底还是我没有关注@AllArgsConstructor这个注解。但此类问题在编译阶段是无法解决的。 ,所以不存在在线错误。

本题主要考察Spring生命周期的一些知识,从中可以衍生出很多知识点。 @Value发生在属性填充阶段,而使用构造函数组装属性则发生在实例化阶段。两者不在同一个阶段,所以如果找不到就会报错。

相关文章