从零开始 Spring Boot 38:Lombok 与依赖注入

从零开始 Spring Boot 38:Lombok 与依赖注入

spring boot

图源:简书 (jianshu.com)

之前的文章中,我详细介绍了 Lombok 的用法,考虑到在 Spring 中使用依赖注入(DI)是如此的频繁,因此有必要讨论使用 Lombok 时可能对依赖注入造成的影响。

我们都知道,Spring 中的依赖注入分为三种情况:

  • 通过属性进行依赖注入。
  • 通过构造器进行依赖注入。
  • 通过 Setter 进行依赖注入。

通过属性进行依赖注入并不会影响我们使用 Lombok,比如:

@RestController
@RequestMapping("/hello")
@Validated
@AllArgsConstructor
public class HelloController {
    @Autowired
    private FibonacciService fibonacciService;

    @GetMapping
    public Result<?> hello(@RequestParam @Min(1) @NotNull Integer n) {
        int fibonacci = fibonacciService.fibonacci(n);
        return Result.success(fibonacci);
    }
}

**无论我们有没有使用构造器注入,用@Autowired标记的属性都会在 bean 实例创建后被 Spring 通过反射来完成注入。**因此实际上这里 Lombok 的@AllArgsConstructor注解生成的构造器并不会对属性fibonacciService的注入产生影响。

构造器注入

下面我们看构造器注入时的情形。

一般的,我们可以将属性设置为final,并借助 Lombok 的@RequiredArgsConstructor注解对需要的属性进行构造器注入:

@RestController
@RequestMapping("/hello")
@Validated
@RequiredArgsConstructor
public class HelloController {
    private final FibonacciService fibonacciService;

    @GetMapping
    public Result<?> hello(@RequestParam @Min(1) @NotNull Integer n) {
        int fibonacci = fibonacciService.fibonacci(n);
        return Result.success(fibonacci);
    }
}

我们知道,在 Spring 的后期版本中,只有一个构造器的情况下是不需要用@Autowired来标记构造器的,Spring 默认会使用这个唯一的构造器进行注入。而在这个示例中,@RequiredArgsConstructor会为我们创建一个包含所有final的非静态属性的构造器,而 Spring 将用这个构造器完成注入。

我们看到,只有一个构造器时(无论是自己编写的还是 Lombok 自动生成的),都不会产生影响,但如果有多个构造器呢?

看下面这个示例:

@RestController
@RequestMapping("/hello")
@Validated
@RequiredArgsConstructor
public class HelloController {
    private final FibonacciService fibonacciService;
    private final Integer n;

    @Autowired
    public HelloController(FibonacciService fibonacciService) {
        this(fibonacciService, 10);
    }

    @GetMapping
    public Result<?> hello(@RequestParam String n) {
        int numN;
        if ("null".equals(n)) {
            numN = this.n;
        } else {
            numN = Integer.parseInt(n);
        }
        if (numN < 1) {
            return Result.fail("hello.input.invalid", "n 不能小于 1");
        }
        int fibonacci = fibonacciService.fibonacci(numN);
        return Result.success(fibonacci);
    }
}

在这个示例中,实际上字节码中会有两个构造器,一个是我们自己编写的有一个参数的构造器,另一个是 Lombok 生成的有两个参数的构造器。

注意,在自己编写的构造器中,我们使用this(...)调用了 Lombok 创建的构造器。

此时如果我们想通过构造器对属性fibonacciService进行注入,就需要告诉 Spring 框架该用哪个构造器完成注入。比较简单的是,如果要用于注入的构造器是我们自己编写的(就像示例中的),我们只需要使用@Autowired标记相应的构造器即可。

如果是反过来,就会有一点麻烦:

@RestController
@RequestMapping("/hello")
@Validated
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class HelloController {
    private final FibonacciService fibonacciService;
    private Integer n = 10;

    public HelloController(FibonacciService fibonacciService, Integer n) {
        this.fibonacciService = fibonacciService;
        this.n = n;
    }

	// ...
}

注意,这里的属性n被修改为非final的。

现在,@RequiredArgsConstructor(onConstructor = @__(@Autowired))将在HelloController类的字节码中生成一个带@Autowired标记的构造器用于注入:

@RestController
@RequestMapping({"/hello"})
@Validated
public class HelloController {
    // ...
    @Autowired
    public HelloController(final FibonacciService fibonacciService) {
        this.fibonacciService = fibonacciService;
    }
}

也就是说,我们可以在 Lombok 用于生成构造器的相应注解中,通过onConstructor属性来指定一系列注解,让 Lombok 在生成构造器时在构造器上添加上这些注解。

这种写法(@__(@Autowired)))有些奇怪,实际上@__是一个并不存在的注解,可以用它来包裹一个注解列表(逗号分隔)来为构造器指定多个用于生成时添加的注解。

Setter 注入

我们知道,在使用 Setter 注入时,必须要使用@Autowired注解。同样的,可以用类似的方式让 Lombok 生成 Setter 时添加上相应的注解:

@RestController
@RequestMapping("/hello")
@Validated
public class HelloController {
    @Setter(onMethod = @__(@Autowired))
    private FibonacciService fibonacciService;
    private final Integer n = 10;
    
    @GetMapping
    public Result<?> hello(@RequestParam String n) {
        // ...
    }
}

The End,谢谢阅读。

这篇文章相对来说简短很多,算是对之前的文章的一个补充。

本文所有的示例代码可以通过这里获取。

参考资料

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值