Python 官方文档:入门教程 => 点击学习
一.前言: ioc(控制反转)与DI(依赖注入) spring框架对Java开发的重要性不言而喻,其核心特性就是ioC(Inversion of Control, 控制反转)和aop
spring框架对Java开发的重要性不言而喻,其核心特性就是ioC(Inversion of Control, 控制反转)和aop,平时使用最多的就是其中的IOC,我们通过将组件交由Spring的IOC容器管理,将对象的依赖关系由Spring控制,避免硬编码所造成的过度程序耦合。
在讲依赖注入之前,我觉得有必要了解一下IOC(控制反转)与DI(依赖注入)的关系,在这篇文章中有详细的介绍:spring IOC 与 DI。
DI的三种常见注入方式为:setter注入、构造器注入和基于注解的注入(也叫field注入),下面来分别讲讲他们的特点。
首先来看一下它的实现:
@RestController
@RequestMapping("/annotation")
public class AnnotationController {
@Autowired
private DiService diService;
@GetMapping("/test001")
public String test001() {
return diService.test001("annotation");
}
}
这种方式应该是目前最常见的注入方式了,原因很简单:
1、注入方式非常简单:加上@Autowired注解,加入要注入的字段,即可完成。
2、使得整体代码简洁明了,看起来美观大方。
在介绍注解注入的方式前,先简单了解bean的一个属性autowire,autowire主要有三个属性值:constructor,byName,byType。
下面进入正题:
注解方式注册bean:
在以前的开发中,我们主要使用四种注解注册bean,每种注解可以任意使用,只是语义上有所差异:
随着SpringBoot的流行,@Bean注解也逐渐的被我们使用起来。Spring的@Bean注解用于告诉方法,产生一个Bean对象,然后这个Bean对象交给Spring管理。产生这个Bean对象的方法Spring只会调用一次,随后这个Spring将会将这个Bean对象放在自己的IOC容器中。
注解方式注入依赖(主要有两种):
关于他们的具体用法与区别,因为内容比较多,所以写在另一篇博客中,请见:@Autowired 和 @Resource 详解
老规矩,先上代码示例:
@RestController
@RequestMapping("/constructor")
public class ConstructorController {
private final DiService diService;
private final String result;
public ConstructorController(DiService diService) {
this.diService = diService;
this.result = diService.test001("constructor");
}
@GetMapping("/test001")
public String test001() {
return diService.test001(this.result);
}
}
这里有一个问题,如果只有一个有参数的构造方法并且参数类型与注入的bean的类型匹配,那就会注入到该构造方法中。如果有多个有参数的构造方法并且每个构造方法的参数列表里面都有要注入的属性,那userDaoJdbc会注入到哪里呢?
在Spring4.x版本中推荐的注入方式就是这种,相较于上面的field注入方式而言,就显得有点难看,特别是当注入的依赖很多(5个以上)的时候,就会明显的发现代码显得很臃肿。对于从field注入转过来+有强迫症的同学来说,简直可以说是石乐志 ,但是为啥spring官方还会这么推荐呢?
官方文档里是这么说的:
The Spring team generally advocates constructor injection as it enables one to implement application components as immutable objects and to ensure that required dependencies are not null. Furthermore constructor-injected components are always returned to client (calling) code in a fully initialized state.
翻译一下就是:Spring团队通常提倡构造函数注入,因为它允许将应用程序组件实现为不可变的对象,并确保所需的依赖不为空。此外,注入构造函数的组件总是以完全初始化的状态返回给客户机(调用)代码。
简单解释一下:
与注解方式注入相比,构造器注入可复用性高,如果使用field注入,缺点显而易见,对于IOC容器以外的环境,除了使用反射来提供它需要的依赖之外,无法复用该实现类。而且将一直是个潜在的隐患,因为你不调用将一直无法发现NPE的存在。
相对于注解注入,构造器注入可以防止循环依赖的问题,若如下代码:
public class A {
@Autowired
private B b;
}
public class B {
@Autowired
private A a;
}
如果使用构造器注入,在spring项目启动的时候,就会抛出:
BeanCurrentlyInCreationException:Requested bean is currently in creation: Is there an unresolvable circular reference?
从而提醒你避免循环依赖,如果是注解注入的话,启动的时候不会报错,在使用那个bean的时候才会报错。
这是在spring3.x出来的时候,官方推荐的注入方式,但是在spring4.x以后就没有见它推荐了,而且在实际开发中已经很少能见到这种注入方式了。
下面来看一下它的实现:
@RestController
@RequestMapping("/setter")
public class SetterController {
private DiService diService;
@Autowired
public void setDiService(DiService diService) {
this.diService = diService;
}
@GetMapping("/test001")
public String test001() {
return diService.test001("setter");
}
}
试想一下,一旦需要注入的组件很多,那我们会累死的,所以大家都不喜欢用它也是情理之中的事情。
这里有一点需要注意:如果通过set方法注入属性,那么spring会通过默认的空参构造方法来实例化对象,所以如果在类中写了一个带有参数的构造方法,一定要把空参数的构造方法写上,否则spring没有办法实例化对象,导致报错。
这么多的依赖注入方式,我们应该怎么选择呢?那种方式最好呢?
其实,有句古话说的很对,合适自己的才是最好的,我们需要看情况来选择使用哪种注入方式。
使用构造器注入的好处:
另外,当有一个依赖有多个实现的使用,推荐使用注解方式注入的方式来指定注入的类型或name,使用setter注入指定类型。这是spring官方博客对setter注入方式和构造器注入的比较。
谢谢大家看完了,以上为个人经验,希望能给大家一个参考,也希望大家多多支持编程网。如果有描述不对的地方欢迎指正,与大家共同进步!
--结束END--
本文标题: 基于spring DI的三种注入方式分析
本文链接: https://www.lsjlt.com/news/129794.html(转载时请注明来源链接)
有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341
下载Word文档到电脑,方便收藏和打印~
2024-03-01
2024-03-01
2024-03-01
2024-02-29
2024-02-29
2024-02-29
2024-02-29
2024-02-29
2024-02-29
2024-02-29
回答
回答
回答
回答
回答
回答
回答
回答
回答
回答
0