
图源:
在中,我详细介绍了 Lombok 的用法,考虑到在 Spring 中使用依赖注入(DI)是如此的频繁,因此有必要讨论使用 Lombok 时可能对依赖注入造成的影响。
我们都知道,Spring 中的依赖注入分为三种情况:
-
通过属性进行依赖注入。
-
通过构造器进行依赖注入。
-
通过 Setter 进行依赖注入。
通过属性进行依赖注入并不会影响我们使用 Lombok,比如:
("/hello")
public class HelloController {
private FibonacciService fibonacciService;
public Result<?> hello( (1) Integer n) {
int fibonacci = fibonacciService.fibonacci(n);
return Result.success(fibonacci);
}
}
无论我们有没有使用构造器注入,用@Autowired标记的属性都会在 bean 实例创建后被 Spring 通过反射来完成注入。因此实际上这里 Lombok 的@AllArgsConstructor注解生成的构造器并不会对属性fibonacciService的注入产生影响。
构造器注入
下面我们看构造器注入时的情形。
一般的,我们可以将属性设置为final,并借助 Lombok 的@RequiredArgsConstructor注解对需要的属性进行构造器注入:
("/hello")
public class HelloController {
private final FibonacciService fibonacciService;
public Result<?> hello( (1) Integer n) {
int fibonacci = fibonacciService.fibonacci(n);
return Result.success(fibonacci);
}
}
我们知道,在 Spring 的后期版本中,只有一个构造器的情况下是不需要用@Autowired来标记构造器的,Spring 默认会使用这个唯一的构造器进行注入。而在这个示例中,@RequiredArgsConstructor会为我们创建一个包含所有final的非静态属性的构造器,而 Spring 将用这个构造器完成注入。
我们看到,只有一个构造器时(无论是自己编写的还是 Lombok 自动生成的),都不会产生影响,但如果有多个构造器呢?
看下面这个示例:
("/hello")
public class HelloController {
private final FibonacciService fibonacciService;
private final Integer n;
public HelloController(FibonacciService fibonacciService) {
this(fibonacciService, 10);
}
public Result<?> hello( 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标记相应的构造器即可。
如果是反过来,就会有一点麻烦:
("/hello")
(onConstructor = ())
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标记的构造器用于注入:
({"/hello"})
public class HelloController {
// ...
public HelloController(final FibonacciService fibonacciService) {
this.fibonacciService = fibonacciService;
}
}
也就是说,我们可以在 Lombok 用于生成构造器的相应注解中,通过onConstructor属性来指定一系列注解,让 Lombok 在生成构造器时在构造器上添加上这些注解。
这种写法(
@__(@Autowired)))有些奇怪,实际上@__是一个并不存在的注解,可以用它来包裹一个注解列表(逗号分隔)来为构造器指定多个用于生成时添加的注解。
Setter 注入
我们知道,在使用 Setter 注入时,必须要使用@Autowired注解。同样的,可以用类似的方式让 Lombok 生成 Setter 时添加上相应的注解:
("/hello")
public class HelloController {
(onMethod = ())
private FibonacciService fibonacciService;
private final Integer n = 10;
public Result<?> hello( String n) {
// ...
}
}
The End,谢谢阅读。
这篇文章相对来说简短很多,算是对的一个补充。
本文所有的示例代码可以通过

文章评论