如何优雅的进行 Bean 注入

不知道为什么,最近听到许多反对使用Lombok的声音,说什么影响代码可读性,具有侵入性。(弱弱的问一句,Entity要什么可读性?)这是我从上学的时候认识Lombok以来,第一次听到这样的声音。

在我看来,Lombok大大提高了开发效率。举个栗子,在我最近工作所开发的ERP系统中,由于行业的特殊性,一张表动辄七八十个字段,难道你会为Entity一个一个的去写setget方法?或者说使用一些工具去生成?反正我打死都不会干的,毕竟人类只有越来越“懒”,才会想尽一切办法去提高生产力。

这篇文章暂且不谈Lombok的优劣,最近我在爬帖子时发现了一个注解,可以优雅的在 Spring 项目中进行 Bean 注入:@RequiredArgsConstructor,这个注解则由Lombok提供。从这个单词来理解,大致就是,必须的参数构造器,那么这个注解又是怎么和Bean注入扯上关系的?向下看。

Bean注入乱象

Spring提供了三种注入模式,一种是属性注入(Filed injection),一种是通过setter方法,一种是构造器注入。就目前情况来看,许多的项目看起来应该是这样的:

1
2
3
4
5
6
7
8
9
10
11
12
13
@Service
public class UserServiceImpl implements UserService {
@Autowired
private ARepo aRepo;
@Autowired
private BRepo bRepo;
@Autowired
private CRepo cRepo;
@Autowired
private DRepo dRepo;
@Autowired
private ERepo eRepo;
}

这样的使用方法本身没有什么问题,看起来还蛮整洁哈,可真实项目里却是这样的:

真实项目截图

Spring从4.0开始,就 不 推 荐 使 用 属 性 注 入 模 式 了, 原因是它可以让我们忽略掉一些代码可能变坏的隐患,同时这样的写法也使IDEA向你发出黄色警告!

既然Spring推荐使用显式的Setter构造器方式,那我们就切换一下实现方案。

这个样子很优雅

Setter方式显然不可能,我可不想把Setter代码生成工具玩到吐,那么就剩下了构造器方式,就像这样:

1
2
3
4
5
6
7
8
9
@Service
public class UserServiceImpl implements UserService {

private final ARepo aRepo;

public UserServiceImpl (ARepo aRepo) {
this.aRepo = aRepo;
}
}

或者……像这样:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
@Service
public class UserServiceImpl implements UserService {

private final ARepo aRepo;
private final BRepo bRepo;
private final CRepo cRepo;
private final DRepo dRepo;
private final ERepo eRepo;

public UserServiceImpl (ARepo aRepo,BRepo bRepo,CRepo cRepo
,DRepo dRepo,ERepo eRepo) {
this.aRepo = aRepo;
this.bRepo = bRepo;
this.cRepo = cRepo;
this.dRepo = dRepo;
this.eRepo = eRepo;
}
}

emmm,要是这样的话,我宁愿用@Autowired

当注入的Bean变多之后,构造器便显得超级臃肿,这个时候@RequiredArgsConstructor就派上了大用场,来看:

1
2
3
4
5
6
7
8
9
10
@Service
@RequiredArgsConstructor
public class UserServiceImpl implements UserService {

final ARepo aRepo;
final BRepo bRepo;
final CRepo cRepo;
final DRepo dRepo;
final ERepo eRepo;
}

嗯,这才是我们想要的样子,相信聪明的你已经明白了@RequiredArgsConstructor会在编译时帮你生成那个又臭又长的构造器,达到了Bean注入的目的。

好了,如此优雅的注入,还不快拿去享用。