categories: Spring
Spring 相关常识
1 Spring家族的介绍
主讲过程
- 第一阶段:Spring core、Spring data
- 第二阶段:Spring boot、Spring Security
- 第三阶段:Spring Cloud
-
2 IOC原理
主讲过程
他是一种思想,并不能算一种技术
IOC(Inversion of Control):控制反转 Spring Core 最核心的部分
- 需要先了解依赖注入(Dependency Inversion)
轮子要改,所有部分都要改,所以秃头。代码如下:上层组件,依赖于下层组件。
这样就避免了依赖,但是下面这种代码,改变了一个值,所有的内容都需要更改,所以这样的代码时不可维护的。
有的类甚至依赖上千个类,那这样更改就要猝死了。。。。
依赖注入下层依靠上层,含义:把底层类作为参数传递给上层类,实现上层对下层的“控制”
直接用代码表示依赖注入的思想:
此时更改尺寸,只需要修改轮子类和主类中的数据即可(这种模式显然利于维护,便于单元测试和协同合作,比如四个部分是四个不同的部门,)。
如果我们要测试行李类,我们只需要箱体类就行,而不是之前的四个类都要初始化。(这里单元测试好像还是要初始化四个类啊,moge一样箱体类就行,这里moge不知道是什么意思,后面学习再深入)
这里依赖注入通过构造函数实现,也可以是用getter和setter、接口等实现
出了DI,还有DL(依赖查找,更为主动的方法,他会在需要的时候,通过调用框架的方法来获取对象,获取时需要提供相关的配置文件路径,key等信息确定获取对象的状态)的实现方式。
DL已经被抛弃,因为它需要用户自己去使用API(有一说一,这和虚拟机底层句柄就很像)查找资源和组装对象,极有侵入性,DI时spring和谷歌等使用的方式。
依赖注入的方式
- Setter
实现特定属性的public方法来让IOC容器调用注入所依赖类型的对象
- Interface
实现特定的接口以供IOC容器注入所依赖类型的对象
- Constructor
构造函数:实现特定参数的构造函数,再创建对象时,让IOC容器注入所依赖类型的对象
- Anotation
通过基于Java注解的机制,来让IOC容器注入所依赖类型的对象,例如 autowired 这一类的标签。
依赖倒置原则
原则时一种思想:高层模块不应该依赖底层模块。两者都应该依赖其抽象(这一句话很关键,依赖于抽象就是内部的事内部管,不管有联系的外界的任何事)
Spring IOC 最重要的就是容器了,容器管理Spring bean的生命周期,控制着bean的依赖注入。(上文中对 luggage 类初始化的代码其实就是容器了,说实话有点抽象,还是实现一遍比较好)
IOC 容器的优势
- 避免在各处使用new来创建类,并且可以做到统一维护(上面两个例子展现了这个事实)
这个容器可以自动对代码进行初始化,你只需要维护一个configuration类就行,可以事xml,或者可以是一段代码,而不用每次初始化一个行李箱,都要亲手去写一大堆初始化的代码
- 创建实力的时候不需要了解其中的细节。
反例中:我们要知道每一个底层的类,才能去创建一个类(极为麻烦)。
IOC容器时反过来的
有点像深度优先遍历,先由上找到最下,再从最下开始初始化,可以隐藏查找的细节,这样就可以有下图的结果。
我们像是工厂的客户,我们只需要向工厂请求一个luggage实例,然后工厂就根据configuration去创建一个luggage实例。并返回给我们,我们不用管这个luggage实例是如何创建出来的。实际项目中,有的servers.class时几十年前写的,有几百个类作为他的底层,假设我们新写了一个API,需要实例化这个servers,我们不可能搞懂几十年前,几百个类的实现内部。大大降低了开发难度,提升了可维护性。
参考阅读
https://juejin.im/post/5b802611518825430a46ca45
https://www.jianshu.com/p/9fe5a3c25ab6
3 SpringIOC的应用
Spring启动时,去读取程序提供的Bean配置信息,并在spring容器中生成一份相应的Bean配置注册表,然后根据这张注册表去实例化Bean,装配好Bean之间的依赖关系,为上层提供准备就绪的运行环境,spring提供一个配置文件,描述Bean和Bean之间的依赖关系,利用Java语言的反射功能实例化Bean,并且建立Bean之间的依赖关系
(我觉得可以实现一下spring容器,或者去看一下spring容器主要源码是如何实现的。)
主讲过程
Spring IOC 支持的功能
- 依赖注入
- 依赖检查
- 自动装配
- 支持集合
- 指定初始化方法和销毁方法
支持回调方法(需要实现spring接口,略带有侵入性的,应该谨慎使用)
Spring 容器的核心接口
BeanFactory(Spring 框架最核心的接口)
提供了IOC的配置机制;
- 包含Bean的各种定义,便于实例化Bean;
- 建立Bean之间的依赖关系;
- Bean生命周期的控制;
BeanFactory的体系结构
Spring的源码特点:看接口的继承关系,以及它们的名字,我们便能大概知道他们的作用。可以看一下BeanFactory的源码,通过查找BeanFactory即可
BeanFactory和ApplicationContext(是前者的子接口之一)之间的比较
- BeanFactory是Spring框架的基础设施,面向Spring
- ApplicationContext 是面向使用Spring框架的开发者
- 前者就想是发动机,后者是完整的一辆车,包含更多其他组件,可以称为高级容器
ApplicationContext的功能(能继承多个接口)
- BeanFactory:能够管理、装配Bean
- ResourcePatternResolver:能够加载资源文件
- MessegeSource:能够实现国际化等功能
- ApplicationEventPublisher:能够注册监听器,实现监听机制
通过@configuration和@Bean来显式装配 Bean,将一个Bean实例注入到容器当中(但是每个都这样初始化,是十分痛苦的事情)
SpringBoot装配Bean的方式:允许我们扫描装配Bean到IOC容器中,对于扫描装配而言,使用的注解是@Component:在实例类中直接进行装配。在实体类中要用@Value来进行赋值;@ComponentScan:扫描已经装配好的Bean。@SpringBootApplication有@componentScan的功能。扫描同级或者是子目录,如果扫描其他包,要在注解后面写一下路径。
@Autowired 是我们在Spring中最常用的注释之一,它会根据属性的类型找到对应的Bean,进行注入,它注入的机制最基本的一条就是根据类型。
更多得情况使用@Primary等,来进一步选择,依赖注入基本上就是这些注解。
先了解一下内容
- BeanDefinition(主要用来描述Bean的定义)
Spring容器在启动的时候,会将xml或者注解里的Bean的定义解析成Spring内部的BeanDefinition
- BeanDefinitionRegistry
提供了向Spring 容器注册 BeanDefinition 对象的方法