标签:tco 有一个 nconf 我不知道 select ring for 实现 try
菜瓜:哥,他们整天说的IOC容器是个啥玩意啊?
水稻:就是Inversion of Control,控制反转啊
菜瓜:哦,原来是控制反转啊,我知道了!你这不是等于白说吗?
水稻:别急,听我慢慢说:
- 想象一下我们平时写测试类,如果不用Spring,我们在A对象里面引用B对象,是不是要自己创建或者引用B,这些操作都是由A来触发的。
- 而如果使用Spring,A需要B的话,直接使用@Autowired注解注入B开箱即用,A不在管B的创建啥的,只需要有个装B的容器给A分配就行了。
菜瓜:就是A引用B本来由自己创建的,结果变成了单位分配对象了。而且如果有多个对象之间存在引用关系就省了好多代码
水稻:deideidei,那你知道Spring的IOC容器初始化是咋做的吗?
菜瓜:你猜我猜不猜?
水稻:Spring启动的过程其实也是IOC容器初始化的过程,如果你不想知道spring的启动过程,那SpringBoot你肯定想知道
- Spring有一个上下文抽象类AbstractApplicationContext,假设你看过SpringBoot的启动类源码(你点一下那个run方法跟进去慢慢找,就能找到)能找到它默认加载了AnnotationConfigApplicationContext子类,然后调用了AbstractApplicationContext的refresh方法。
- 先看AnnotationConfigApplicationContext。你知道的@Autowired@Resource@ComponentScan@Bean@Import@Configuration注解的功能解析类都是从它这里注册的。初始化它的时候会调用方法AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);该方法会注册BeanFactoryPostProcessor和BeanPostProcessor接口实现类到BeanDefinitionNames中,最为关键的ConfigurationClassPostProcessor为SpringBoot启动类上的注解提供了支撑
- 再回过头来看refresh方法,挑重要的讲,它会实例化BeanFactoryPostProcessor接口实现类ConfigurationClassPostProcessor并解析@Configuration和@Import@ComponentScan注解
- 回头看SpringBoot启动类上的@SpringBootApplication注解
- @ComponentScan注解:ConfigurationClassPostProcessor在解析该注解时会通过一个扫描类扫描指定路径下的class文件,将所有带有@Component注解的类搜集到BeanDefinitionNames容器中,方便后面实例化
- @SpringBootConfiguration注解:标识该类被IOC容器管理
- @EnableAutoConfiguration:Imoprt了AutoConfigurationImportSelector类。该类回去加载META-INFO/spring.factories文件里面的类,包括有web容器,默认配置等
菜瓜:我懵逼了,这A和B的创建还没开始,你整这么多我不知道的东西干啥?
水稻:我的,我的。上面讲的是SpringBoot的启动流程,是IOC容器的准备阶段。你可以略过,我们进入IOC正式阶段
- 概括下来就是,Spring会通过扫描器的形式去扫描我们指定包路径下的.class文件(SpringBoot没配置的情况下,默认是启动类所在包,你要是不小心将启动类挪走了,你会发现扫描不到文件)。将带有@Component注解(包括其子类)的类封装成BeanDefinition加入一个大的BeanDefinitionMap容器中,与之对应的还有一个BeanDefinitionNames
- 之后会for循环这个BeanDefinitionNames,单独加载每一个类,放入IOC容器,也就是一个大的ConcurrentMap中
菜瓜:哦,你这么说我就能听懂了。那他们说的循环依赖,很多的BeanPostProcessor还没介绍呢?
水稻:溜了溜了,你等我吃完饭回来再和你说
Spring:IOC容器到底是咋肥事啊?
标签:tco 有一个 nconf 我不知道 select ring for 实现 try
原文地址:https://www.cnblogs.com/nightOfStreet/p/13042718.html