点击上方“芋道源码”,选择“设为星标”
管她前浪,还是后浪?
能浪的浪,才是好浪!
每天 10:33 更新文章,每天掉亿点点头发...
源码精品专栏
问题原因
关于这个问题,其实答案相对统一,实际上用大白话说起来也容易理解。
1.初始化问题
先看一下Java初始化类的顺序:
父类的静态字段 > 父类静态代码块 > 子类静态字段 > 子类静态代码块 > 父类成员变量 > 父类构造代码块 > 父类构造器 > 子类成员变量 > 子类构造代码块 > 子类构造器
而Autowired注入,则要排队到子类构造器以后了,SpringIOC并不会对依赖的bean是否为null做判断,JVM编译时同样也不会有问题,但如果使用不当,运行起来时或许会因为出现空指针异常。
2.对IOC容易依赖过强
@Autowired
由Spring提供,而@Resource
是JSR-250提供的,它是Java标准。前者会警告,而后者不警告,就是因为前者导致了应用与框架的强绑定,若是换成其他IOC框架,则不能够成功注入了。其实对于这方面,我认为在大多数情况时是不会有什么问题的。
3.其他方面
我看到网络上有一些其他方面的总结,比如:依赖过多却不够明显,违反了单一职责原则;不能像构造器那样注入不可变的对象等,这类问题需要结合个人实际开发进行判断。
对于@Autowired
使用方面,它虽然是将业务代码和框架进行了强绑定,但字段注入确实大幅简化了代码。追求完完全全的松耦合其实也过于理想化,应该在实际使用中追求平衡,否则将为了过度追求松耦合而得不偿失。
基于 Spring Boot + MyBatis Plus + Vue & Element 实现的后台管理系统 + 用户小程序,支持 RBAC 动态权限、多租户、数据权限、工作流、三方登录、支付、短信、商城等功能
项目地址:https://github.com/YunaiV/ruoyi-vue-pro
视频教程:https://doc.iocoder.cn/video/
其他使用方式
除了使用@Autowired
以外,我们其实也有几种好用的方式。使用@Resource
替代@Autiwired
方法是其中一种,只需要改变一个注解,这里就不展示了。
1.set方法
@RestController
public class TestController2 {
ITestService testService;
/*
* 基于set注入
* */
@Autowired
public void setTestService(ITestService iTestService) {
this.testService = iTestService;
}
@GetMapping("/status2")
public Result<?> status() {
return testService.status();
}
}
这种方法也使用了@Autowired
注解,但是它是作用于成员变量的Setter函数上,而不是像Fied注入一样作用于成员变量上。
2.构造器
@RestController
public class TestController1 {
ITestService testService;
/*
* 基于构造方法的注入
* */
public TestController1(ITestService iTestService) {
this.testService = iTestService;
}
@GetMapping("/status1")
public Result<?> status() {
return testService.status();
}
}
它的好处在于,采用了构造方法注入,这种方式对对象创建的顺序会有要求,它将避免循环依赖问题。是最可靠的方法。
3.构造器的简化版(推荐)
首先,需要引入lombok依赖。
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.2</version>
</dependency>
随后,我们在创建时就可以使用@RequiredArgsConstructor
注解,它将帮我们创建构造器,final关键字必不可少。
@RestController
@RequiredArgsConstructor
public class TestController3 {
/*
* 用@RequiredArgsConstructor注解,这个使用方式也可以应用于service层
* */
private final ITestService testService;
@GetMapping("/status3")
public Result<?> status() {
return testService.status();
}
}
我们在使用这些创建方法时,都可以调出IDEA的结构(Structure)面板进行查看,如下图所示。
可以看到,在这个类中,已经存在我们所需要注入的内容。
在网上有博主总结了一张表,但因为到处能看到,不知原来出处是哪里。
注入方式 | 可靠性 | 可维护性 | 灵活性 | 循环关系检测 | 性能 |
---|---|---|---|---|---|
Field注入 | 不可靠 | 低 | 灵活 | 不检测 | 启动快 |
构造方法 | 可靠 | 高 | 不灵活 | 检测 | 启动慢 |
set方法 | 不可靠 | 低 | 灵活 | 不检测 | 启动快 |
基于 Spring Cloud Alibaba + Gateway + Nacos + RocketMQ + Vue & Element 实现的后台管理系统 + 用户小程序,支持 RBAC 动态权限、多租户、数据权限、工作流、三方登录、支付、短信、商城等功能
项目地址:https://github.com/YunaiV/yudao-cloud
视频教程:https://doc.iocoder.cn/video/
总结
在使用中,使用构造方法是比较可行的,加上lombok,其实也可以到达非常简便。
欢迎加入我的知识星球,一起探讨架构,交流源码。加入方式,长按下方二维码噢:
已在知识星球更新源码解析如下:
最近更新《芋道 SpringBoot 2.X 入门》系列,已经 101 余篇,覆盖了 MyBatis、Redis、MongoDB、ES、分库分表、读写分离、SpringMVC、Webflux、权限、WebSocket、Dubbo、RabbitMQ、RocketMQ、Kafka、性能测试等等内容。
提供近 3W 行代码的 SpringBoot 示例,以及超 4W 行代码的电商微服务项目。
获取方式:点“在看”,关注公众号并回复 666 领取,更多内容陆续奉上。
文章有帮助的话,在看,转发吧。
谢谢支持哟 (*^__^*)