欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Spring揭秘日志——(番外)SpringIOC容器创建流程梳理

程序员文章站 2022-05-19 11:20:12
前几天看完了Spring揭秘的第四章,内容有点多,这几天在准备面试,还没来得及写日志,但是看完第四章想起以前在尚硅谷雷丰阳老师的带领下追SpringIOC创建容器的源码,而在Spring揭秘的第四章中这些知识点也很零散所有今天来把上次追源码的笔记整理出来。(注意,笔记都是从refresh()方法展开的,标号都是有方法间的层次关系)=========================================================Spring容器的refresh()【创建刷新】(1)pre...

前几天看完了Spring揭秘的第四章,内容有点多,这几天在准备面试,还没来得及写日志,但是看完第四章想起以前在尚硅谷雷丰阳老师的带领下追SpringIOC创建容器的源码,而在Spring揭秘的第四章中这些知识点也很零散所有今天来把上次追源码的笔记整理出来。(注意,笔记都是从refresh()方法展开的,标号都是有方法间的层次关系)

=========================================================

Spring容器的refresh()【创建刷新】

(1)prepareRefresh()刷新前的预处理;

①InitPropertySources();初始化一些属性设置;子类自定义个性化的属性设置方法
②getEnvironment().validateRequiredProperties();检验属性的合法等。
③this.earlyApplicationEvents = new LinkedHashSet();保存容器中的一些早期事件。
(2)ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();获取bean工厂。
①refreshBeanFactory();刷新BeanFactory;创建一个this.beanFactory = new DefaultListableBeanFactory(); 设置ID
②getBeanFactory();返回刚才GenericApplicationContext创建的BeanFactory对象;
③将创建好的BeanFactory返回(DefaultListableBeanFactory)返回。

(3)prepareBeanFactory(beanFactory);BeanFactory的预准备工作

Spring揭秘日志——(番外)SpringIOC容器创建流程梳理
①设置BeanFactory的类加载器、支持表达式解析器
②添加部分的BeanPostProcessor比如【ApplicationContextAware】
③设置忽略的自动装配接口比如【EnvironmentAware、ApplicationEventPublisherAware】
④注册可以解析的自动装配,我们能直接在任何组件中自动注入;如【BeanFactory、ResourceLoader、ApplicationContext】
⑤添加后置处理器【beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));】beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));
⑥添加编译时的AspectJ
⑦给BeanFactory中注册一些能用的组件

(4)postProcessBeanFactory(beanFactory);// Allows post-processing of the bean factory in context subclasses. BeanFactory准备工作完成后进行的后置处理工作。

①子类通过重写这个方法来在BeanFactory创建并预准备完成以后做进一步的设置。
Spring揭秘日志——(番外)SpringIOC容器创建流程梳理

(5)invokeBeanFactoryPostProcessors(beanFactory);执行BeanFactoryPostProcessors(BeanFactory的后置处理器)。在BeanFactory标准初始化之后执行。(就是以上四点)

①两个接口:BeanFactoryPostPrecessor、BeanDefinitionRegistryPostProcesor
②执行BeanFactoryPostProcessors
1)获取所有的BeanDefinitionRegistryPostProcessor;
2)看优先级排序 看先实现了PriorityOrdered优先级接口的BeanDefinitionRegistryPostProcesor;
3)再执行实现了Order顺序接口的BeanDefinitionRegistryPostProcessor;
4)最后执行没有实现任何优先级、顺序接口的postProcessor.BeanDefinitionRegistryPostProcessor;
③再执行BeanFactoryPostProcessor的方法。
1)获取所有的BeanFactoryPostProcessor
2)看优先级排序 看先实现了PriorityOrdered优先级接口的BeanDefinitionRegistryPostProcesor;
3)再执行实现了Order顺序接口的BeanDefinitionRegistryPostProcessor;
4)执行没有实现任何优先级、顺序接口BeanDefinitionRegistryPostProcessor;

(6)registerBeanPostProcessors(beanFactory);注册BeanPostProcessor(Bean的后置处理器) (不同接口类型的BeanPostProcessor;在Bean创建的前后时机是不一样的)

①获取所有的BeanPostProcessor;后置处理器默认可以通过PriorityOrdered、Ordered接口来执行优先级。
②先注册有PriorityOrdered接口的BeanPostProcessor;把每一个BeanPostProcessor添加到BeanFactory中
③再注册Order
④最后注册没有实现Order、PriorityOrdered的接口。
⑤最终注册MergedBeanDefinitionPostProcessor;
⑥还会注册一个ApplicationListenerDetector;来在Bean创建完成后检查是否是ApplicationListener

(7)initMessageSource();初始化MessageSource组件(做国际化功能,消息绑定,消息解析);

①获取BeanFactory
②查看BeanFactory中是否有id为messageSource的,类型时MessageSource的组件。如果有赋值给messageSource,如果没有自己创建一个DelegatingMessageSource;MessageSource:取出国际化配置文件中的某个key的值,能按照区域信息获取。
③把创建好的MessageSource注册到容器中,以后获取国际化配置文件的值的时候,可以自动注入MessageSource。调用就直接使用getMessage方法。

(8)initApplicationEventMulticaster();初始化事件派发器。

①获取BeanFactory;
②从BeanFactory中获取applicationEventMulticaster的ApplicationEventMulticaster
③如果上一步没有配置,就创建一个SimpleApplicationEventMulticaster
④将创建的ApplicationEventMulticaster添加到BeanFactory中,以后其他组件直接自动注入。

(9)onRefresh():留给子类

①子类重写这个方法,在容器刷新的时候可以自定义逻辑。

(10)registerListeners();给容器中所有项目里面的ApplicationListener注册进来添加到时间派发器中;

①从容器中拿到所有的ApplicationListener
②将每个监听器添加到时间派发器中。
③派发之前步骤产生的事件。

(11)finishBeanFactoryInitialization(beanFactory);初始化所有剩下的单实例Bean.

①beanFactory.preInstantiateSingletons();初始化后剩下的单实例Bean(具体方法见下图)
Spring揭秘日志——(番外)SpringIOC容器创建流程梳理
1)获取容器中的所有Bean,依次进行初始化和创建对象。
2)获取Bean的定义信息:RootBeanDefinition
3)Bean此时不是抽象的,是单实例的,不是懒加载的;
a.判断是否是FactoryBean;是否是实现FactoryBean接口的
b.不是FactoryBean,利用getBean(beanName);创建对象
a)getBean(beanName);ioc.getBean;
b)getBean方法中调用doGetBean(name, null, null, false);
c)先获取缓存中保存的单实例Bean(所有创建过的单实例Bean都会被缓存起来)从private final Map<String,Object> singletonObject = new ConcurrentHashMap<String,Object>()中获取。
d)缓存中获取不到,开始Bean的创建对象流程
e)标记当前创建的bean
f)获取bean的定义信息
g)获取当前Bean依赖的其他的Bean;如果有按照getBean()把依赖的Bean先创建出来;
h)启动单实例Bean的创建流程
i.调用createBean(beanName,mdb,args);
ii.实现 Object bean = resolveBeforeInstantiation(beanName,mdbToUse);让BeanPostProcessor先拦截返回代理对象。(这里为了提前执行InstantiationAwareBeanPostProcessor)触发postProcessorBeforeInstantiation();如果有返回值之后便触发postProcessorAfterInstantiation()
iii.InstantiationAwareBeanPostProcessor没有返回代理对象;
iv.调用Object beanInstance = doCreateBean(beanName,mdbToUse,args);创建Bean;
i)创建Bean实例createBeanInstance(beanName,mdb,args)利用工厂方法或者对象的构造器创建出Bean实例。
ii)applyMergedBeanDefinitionPostProcessors(mdb,beanType,beanName);
v.【Bean属性赋值】populateBean(beanName,mdb,instanceWrapper);
i)赋值之前拿到InstantiationAwareBeanPostProcessor后置处理器执行postProcessorAfterInstantiation();
ii)赋值之前拿到InstantiationAwareBeanPostProcessor后置处理器执行postProcessPropertyValues();
iii)应用Bean属性的值:这才是为Bean属性赋值调用为利用setter方法等进行赋值applyPropertyValues(beanName,mdb,bw,pvs);
vi.【Bean初始化】initializeBean(beanName,exposedObject,mdb);
i)【执行Aware接口方法】执行invokeAwareMethods(beanName,bean);执行Aware接口的方法,看是否实现了BeanNameAware、BeanClassLoaderAware、BeanFactoryAware
ii)【执行后置处理器初始化之前】applyBeanPostProcessorBeforeInitialization();
iii)【执行初始化方法】invokeInitMethods(beanName,wrappedBean,mbd);
a.是否是InitializingBean接口的实现,执行接口规定的初始化。
b.是否自定义初始化方法
iv)【执行后置处理器初始化之后】applyBeanPostProcessorAfterInitialization();
vii.注册Bean的销毁方法:
i)Bean实例创建完成,并且将Bean实例保存到缓存中。
j)之后检查所有的Bean是否是SmartInitializingSingleton接口的如果是就执行afterSingletonsInstantiated();

(12)finishRefresh()完成刷新工作;完成BeanFactory的初始化创建工作;IOC容器就创建完成了;

①初始化与生命周期有关的后置处理器initLifecycleProcessor()允许实现lifecycleProcessor
②拿到定义的生命周期处理器进行一个回调getLifecycleProcessor().onRefresh();
③publishEvent(new ContextRefreshedEvent(this));发布容器刷新完成事件
3、

IOC容器创建总结:

1、Spring容器在启动的时候,先会保存所有注册进来的Bean的定义信息
(1)xml注册的Bean
(2)注解的bean
2、Sping容器会合适的时机创建Bean
(1)用到这个bean的时候,采用getBean创建bean;创建好以后保存在容器中;
(2)统一创建剩下所有的bean的时候,finishBeanFactoryInitialization();
3、后置处理器:每个bean创建完成,都会使用各种1后置处理器进行处理,来增强bean的功能;(如自动注入 是靠AutowiredAnnotationBeanPostProcessor处理的)

因为是直接用之前写好的word所有有些格式很蛋疼,序号的关系如下图(以(11)点位例子)
Spring揭秘日志——(番外)SpringIOC容器创建流程梳理

本文地址:https://blog.csdn.net/qq_42942472/article/details/107383071