Spring的启动流程概述:
核心方法:
refresh方法,作用就是实例化spring容器中的所有单例。
3步:
- 生成BeanFactory容器(有beanDefinition类信息和bean对象实例)
- 生成BeanDefinition类信息
- 生成bean对象实例
需要知道的知识:
1、先有beanDefinition类信息,再有bean对象。
2、在beanDefinition和bean前后spring有增加拓展点,拓展点统一用PostProcessor封装。所以流程是:
- 生成BeanFactory容器
- beanDefinitionPostProcessor处理、生成BeanDefinition类信息、beanDefinitionPostProcessor处理
- beanPostProcessor处理、生成bean对象实例、beanDefinitionPostProcessor处理
Spring的启动流程具体一点:
1、生成BeanFactory容器。(即ApplicationContex、AnnotationConfigApplicationContex)
- 创建BeanFactory
- 然后往BeanFactory中丢入基础的PostProcessor处理器的BeanDefinition。
核心是生成PostProcessor的BeanDefinition。这里的PostProcessor处理器主要是BeanDefinition和Bean的PostProcessor处理器,如BeanDefinitionRegistryPostProcessor、ConfigurationClassPostProcessor、EventListenerMethodProcessor等,主要涉及beanDefinition注册、autowired自动注入、aware回调、eventListener事件监听有关的。
2、生成BeanDefinition类信息
- 调用上面放入的BeanFactoryPostProcessor处理器的方法,走方法逻辑,从而得到更多的BeanDefinition。
如调用ConfigurationClassPostProcessor这种beanDefinition注册有关的处理器的方法,就会描相应目录下的@component等生成BeanDefinition、解析@Import,@Bean生成BeanDefinition等。
- 生成国际化messageSource、事件发布applicationEventMulticaster的BeanDefinition
3、生成bean对象实例(单例bean)
创建对象过程是:实例化(1-3)、处理属性(5-7)、初始化(8-10)。涉及到之前加入的Bean的PostProcessor的beanBefinition的处理
1.实例化前。InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation()
2.实例化
3.实例化后。MergedBeanDefinitionPostProcessor.postProcessMergedBeanDefinition()
4.InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation()
5.自动注入(依赖注入)
6.属性处理。InstantiationAwareBeanPostProcessor.postProcessProperties()。如@autowired
7.回调处理一些类信息。Aware对象
8.初始化前。BeanPostProcessor.postProcessBeforeInitialization()
9.初始化。执行InitializingBean初始化接口
10.初始化后。BeanPostProcessor.postProcessAfterInitialization()。如aop
配置类解析流程
会给个初始@Component(一般是AppConfig.class)到ApplicationContex中作为入口。对@Component的处理逻辑如下:
1、@Component的bean就会生成beanDefinition上交spring容器,(含@Controller、@Service、@repository、@configuration,这些都是@Component),如果里面有内部类也有@Component,则递归。
2、如果有@ComponentScan,则扫描获取@Component,并生成beanDefinition上交spring容器
3、如果有@Import、@Bean等都生成beanDefinition上交spring容器
@Import、@Configuration、@Bean区别:
1、@Configuration是@Component,自己项目的spring都读取到。@Import和@Bean不是@Component,所以自己项目的spring读取不到,所以需和@Configuration一起用,这样spring就能读到@Component,进而读到@Import和@Bean,走@Import和@Bean的逻辑。
2、当然@Import和@Bean也可以和@Component一起用,但是@Configuration本身就是@Component,用@Configuration有一种标识作用,让人一看就知道这是个导入外部类的配置类,就和@Controller一样,让人一看就知道这个是controller层。
3、@Import(UserConfig.class)和@Bean都是导入外部bean,@Import侧重于导入一个配置类(这个配置类一般是个大入口,里有多个bean,多个bean会注册到spring中),@Import打在类上,@Bean侧重于导入单个bean,@Bean打在方法上。