深入浅出Spring Boot 2.X 学习笔记 第三章

第三章 全注解下的Spring IoC

IoC是一种通过描述来生成或者获取对象的技术。Java中可以使用new 关键字来创建对象,而Spring则是通过描述来创建对象。由于Spring Boot不建议使用XML,所以通过注解的描述生成对象。
Spring中把每一个需要管理的对象称为Spring Bean,而Spring管理这些Bean的容器,被我们称为Spring IoC容器。
IoC容器需要具备两个基本的功能:

  • 通过描述管理Bean,包括发布和获取Bean;
  • 通过描述完成Bean之间的依赖关系。

总结:
问:什么是控制反转(Inversion of Control,IoC)?
答:IoC是一种通过描述生成或者获取对象的技术,传统的获取对象的方式是通过new来创建一个对象。而IoC中对象是由IoC容器来控制,当我们需要一个对象的时候,直接通过IoC容器来获取对象。

3.1 IoC容器简介

在Spring中,所有的IoC容器都需要实现接口BeanFactory。在BeanFactory中有多个getBean方法。这是IoC容器最重要的方法之一,他的意义是从IoC容器中获取Bean。多种getBean方法允许我们按类型或者名称获取Bean。

@Configuration注解代表这是一个Java配置文件,Spring的容器会根据@Configuration来生成IoC容器去装配Bean;
@Bean会将方法返回的POJO(Plain Ordinary Java Object)装配到IoC容器中
之后,可以通过AnnotationConfigApplicationgContext来构建自己的IoC容器。

总结:
问:什么是IoC容器?
答:Spring中一个管理Bean的容器。用来创建Bean,并控制Bean的整个生命流程。

3.2 装配你的Bean

3.2.1通过扫描装配你的Bean

除了@Bean可以将Bean注入到Spring IoC容器中,Spring 还可以通过扫描装配来进行注入,扫描装配有两个注解可以使用@Component和@ComponentScan。
@Component是标明那个被扫描进入Spring IoC容器。
@ComponentScan是标明采用何种策略去扫描装配的Bean。

我们可以通过@Component和@ComponentScan来使得IoC容器可以去扫描类。
@Service也注入了@Component,所以拥有@Service的类也会被扫描装配到IoC容器中。
@ComponentScan拥有多种扫描策略,我们可以通过ComponentScan的源码来更深刻的理解和设置不同的扫描策略,例如定义扫描的包和过滤器。

@SpringBootApplication中也注入了@ComponentScan,如果不需要特殊的扫描策略,可以直接使用@SpringBootApplication即可。

3.2.2 自定义第三方Bean

很多时候,我们希望把第三方包的类对象也放到Spring IoC容器中,这时我们就可以通过@Bean来实现。
首先通过pom.xml来导入依赖,然后就可以通过@Bean把返回的目标对象保存到IoC容器中。

3.3 依赖注入

Bean之间的依赖,在Spring IoC的概念中,被称为依赖注入。
例如,人(Person 类)利用狗(Dog 类)来看门。人不会去看门,但是他需要狗去为他看门。

@Autowired是Spring中最常用的注解之一,它会根据属性的类型找到对应的Bean进行注入。

3.3.1 注解@Autowired

@Autowired的注入机制中最基本的一条是根据类型(by type),而IoC容器的顶级接口BeanFactory中的getBean方法获取对应的Bean时,就支持根据类型根据名称
@Autowired会先根据类型找到Bean,如果对应类型的Bean不唯一,会继续根据属性名称来进行匹配,如果匹配上了就使用该Bean,没有匹配上就抛出异常。
@Autowired默认必须找到Bean,如果不确定是否可以找到对应的Bean可以通过配置required属性来改变。

3.3.2 消除歧义性——@Primary和@Qualifier

上一章节说到,如果我们遇到了类型相同的多个Bean,IoC会无法区分,因此可以通过选择更详细的类型来区分注入正确的Bean。
如果我们不想修改注入的Bean类型,我们还可以通过@Primary和@Quelifier来注入我们想要的Bean。
@Primary,是一个修改优先权的注解,我们在想注入的类上添加一个@Primary注解,那么如果遇到相同类型的Bean,就会优先注入拥有@Primary的Bean。

当多个类都被添加了@Primary的话,那么情况就又回到了最初的时候,这时候我们还有其他办法,我们可以利用@Qualifier注解来规定我们需要的Bean类型。

3.3.3 带有参数的构造方法类的装配

对于带有参数的构造方法,我们需要在构造方法的参数上进行一些修改。
(@Autowired @Qualifier(“xxx”) ClassA classA)

3.4 生命周期

Bean的生命周期,大致分为Bean定义、Bean初始化、Bean的生存期和Bean的销毁4个部分。

Bean的定义过程

  1. 通过@ComponentScan定义的扫描路径找到带有@Component的类
  2. 找到后,进行解析,将定义信息保存起来。
  3. 把Bean定义发布到Spring IoC容器中,此时也只是Bean的定义,还没有实例生产。

将Bean的定义发布到IoC容器的过程中,还没有Bean实例的生成,更没有完成依赖注入。在默认情况下,Spring会继续完成Bean的实例化和依赖注入,这样就可以从IoC容器中得到一个依赖注入完成的Bean。但是Bean会受到变化因素的影响,有时候我们希望取出的时候再完成初始化和依赖注入。
Spring Bean的初始化流程

  1. @ComponentScan完成资源定位
  2. Bean定义保存到BeanDefinition实例中完成Bean定义
  3. IoC容器装在Bean定义完成发布Bean定义
  4. 创建Bean的实例对象完成实例化
  5. 通过@Autowired完成依赖注入

@ComponentScan中有一个配置lazyInit可以配置Boolean值,默认为false,默认不进行延迟初始化。因此会弄人自动进行实例化和依赖注入。

Spring IoC容器最低的要求是实现BeanFactory接口,如果实现了Spring Bean 生命周期中的全部接口,那么这个Bean就可以实现单个Bean生命周期中所有接口功能。例如@PsotConstruct来定义初始化方法,@PreDestroy来销毁方法。

3.5 使用属性文件

Spring Boot 中我们可以使用默认为我们准备的application.properties来配置属性。
我们可以在类中使用@Value注解,来获取配置文件中的内容。

我们还可以通过@ConfigurationProperties将与POJO的属性名称组成属性的全限定名去配置文件里查找,也能将配置文件中对应的属性导入到POJO中。

3.6 条件装配Bean

@Conditional注解可以帮助我们处理一些需要判断的情况。
@Conditional(DatabaseConditional.class)需要配合Condition接口来完成对应功能。通过Conditional中配置的class来实现Condition接口,在class中实现功能判断,来实现一些条件判断来装配Bean。

3.7 Bean的作用域

IoC容器的顶级接口BeanFactory中,有isSingleton和isPrototype两个方法。isSingleton为true时(默认值),Bean在IoC容器中则以单例存在。如果isPrototype方法返回true,每次获取的Bean都会由IoC容器创建一个新的Bean。
如果不设置isPrototype,无论创建几个实例,实际上都是同一个实例。如果启用了isPrototype,创建了几个实例,就会真正的生成几个实例。

3.8 使用@Profile

Spring提供的Profile机制,可以轻松的实现不同开发环境之间的切换。主要是数据库资源和其他服务资源。

3.9 引入XML配置Bean

虽然Spring Boot建议使用注解扫描配置Bean,但是也还可以通过XML配置Bean。@InportResource可以引入对应的XML文件,从而加载Bean。

3.10 使用Spring EL

Spring EL是表达式语言,可以拥有强大的运算规则来更好的装配Bean。
Spring El可以进行数学运算、浮点数比较运算、字符串比较运算、字符串连接、三元运算等。

参考文章
本文链接:https://www.zhihu.com/question/335362570

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值