一、Spring
1.IOC
IOC的启动流程
主要分为两步,注册和初始化
注册
1.首先会创建一个Default容器工厂
2.调用资源解析类将xml文件解析成Resource
3.通过调用一个类将Resource解析成Document对象
4.委托一个类将其封装为BeanDefinition
5.以对象名为key,BeanDefinition对象为value,通过BeanDefinitionRegistry将对象注册到工厂的Map里。
初始化
Spring只会对单例且非懒加载的类进行初始化。而多例或懒加载的是等到使用的时候才去初始化。
主要是通过AbstractBeanFactory中的doGetBean去初始化对象,但是这个过程中会先去缓存中拿,这时为了解决循环依赖的问题,通过三个Map缓存来解决setter类型循环依赖。当对象实例化完成后,最后通过populateBean完成属性的注入。
循环依赖的问题
spring是通过三个Map作为缓存来解决setter方式的循环依赖问题,构造器循环依赖解决不了会直接报错,其分别是一级缓存singletonObjects、二级缓存earlySingletonObjects、三级缓存singletonFactories
假设A类中依赖B,B又依赖了A,具体的执行流程如下:
1.A所有缓存中都获取不到对象,会调用A的构造方法,将其放入singletonFactories中
2.对A进行属性注入,发现其依赖了B
3.初始化B的时候在所有缓存都获取不到对象,调用B的构造方式,将其放入singletonFactories中
4.对B进行属性注入,发现它依赖了A
5.初始化对象A,在三级缓存发现其对象,直接获取,将其放如二级缓存,将A从三级缓存删除
6.对象B的依赖注入完成,将其放入一级缓存,将B从二级和三级缓存删除
7.将对象B注入给对象A,再注入其他依赖,直到所有的注入完成
8.对象A创建完成,将其放入一级缓存,将A从二级和三级缓存删除
9.对象A和对象B初始化完成
二、SpringBoot
1、自动装配原理
首先SpringBoot项目启动时候会去找到其主入口@SpringBootApplication,这是一个复合注解
里面有一个注解@EnableAutoConfiguration就是开启自动配置,在其内部又通过@Import引入了AutoConfigurationImportSelector类。
在这个类里面它通过调用SpringFactortriesLoader类中的loadFactoryNames去加载META-INF包下的spring.factories这个文件。这个配置文件中就是所有想要自动装配到容器的一些类,其中最重要的就是XXXAutoConfiguration,redis就是RedisAutoConfiguration。
而在这个类中它有一个注解@EnableAutoConfigurationProperties去加载配置类,配置类就用@AutoConfigurationProperties去yml配置文件中读取配置。在这个类中还有其他自动装配配置,@ConditionalOnMissingBean:只有这个Bean在容器中不存在,才会自动配置现在这个Bean
@ConditionalOnClass:只有容器中存在这个字节码文件,才会使用该配置。典型的使用就是DataSource,选择配置哪一种连接池
2.自定义Starter
如果想要自定义starter让容器帮我们自动配置,首先必须要有最重要的三个文件。
1.spring.factories
2.XXXAutoConfiguration
3.XXXProperites
首先我们要根据规范,在META-INF包下创建spring.factories配置文件,里面写上XXXAutoConfiguration的全限定名,表示这个类需要自动装配。
在XXXAutoConfiguration加上@EnableAutoConfigurationProperties(XXXProperties.class),表示去加载这个配置类,在XXXProperites中加注解@AutoConfiguationProperites(cn.yyh)。将其打成jar包放到项目中,这样当项目启动的时候,它就会去yml配置中找以cn.yyh开头的配置并进行自动装配。
3.启动流程
首先肯定是去找我们的启动类中run方法,而run方法内部其实是去调用了SpringApplication.run。这个方法内部它实现了很多功能
1.开启秒表计时
2.启动监听器
3.加载环境对象
4.打印banner横幅
5.创建Spring容器对象
6.容器刷新前置工作
7.刷新容器
8.容器刷新后置工作
9.停止秒表
10.调用runner去启动程序
我们可以通过它的启动流程,来实现一些功能。
1.通过ApplicationListener监听器,来实现在容器刷新、创建、销毁的时候做一些事情
2.通过@PostConstruct加在方法上,它会在Bean创建完成后就去自动调用这个方法,可以用来在Bean创建完之后进行一些初始化操作。