spring ioc原理 - 源码流程重点标注指南

137 阅读3分钟

世界上并没有完美的程序,但是我们并不因此而沮丧,因为写程序就是一个不断追求完美的过程。

spring框架的源码是所有框架源码中最难的源码之一,但是又是最重要的,因为现今绝大多数的应用都是在spring框架的基础上构建起来的。spring有两大核心IOC和AOP,其中IOC又是核心中的核心,所以掌握IOC的源码是非常必要的。本文主要遵循最小知识点的原则,将ioc所有源码以方法的形式分层标注一遍,旨在突出重点,希望成为大家阅读spring ioc源码的一个指南。

说明:文中标注"(略)“的简单知道就行;标注”(记下)“的是需要注意的,但无需深入;标注”(重点)“的是真正的重点,需要深入debug进行分析的。文中所有方法与源码中完全一致,并且都是顺序解释的,可以对照查看;每一层开始都会明确的标出该层的入口方法,其中入口方法就是上一层标注的重点,如果上一层有多个重点方法,下一层会以”(重点x)"的形式标注出来,注意它们的关系是平行的而不是递进。以下是分层标注的内容:

第一层:new ClassPathXmlApplicationContext(configLocation)
->new ClassPathXmlApplicationContext(configLocation) = 容器入口
-> this([] configLocation, refresh, parent)
-> super(parent) = 加载父类(略)
-> setConfigLocation(configLocation) = 资源路径解析(略)
-> refresh() = IOC 容器刷新(重点)

第二层:refresh() (重点)
-> synchronized(this.startupShutDownMonitor) = 线程安全(记下)
-> prepareRefresh() = 容器刷新前准备(略)
-> obtainFreshBeanFactory() = 刷新BeanFactory,配置标准化解析(重点)
-> prepareBeanFactory(beanFactory) = beanFactory使用前的一些配置(略)
-> postProcessBeanFactory(beanFactory) = 自定义扩展的位置(记下)
-> invokeBeanFactoryPostProcessors(beanFactory) = 自定义扩展的调用(略)
-> registerBeanPostProcessors(beanFactory) = 注册自定义扩展的Bean(略)
-> initMessageSource() = 国际化(略)
-> initApplicationEventMulticaster() = 事件组播(略)
-> onRefresh() = 特殊扩展刷新(略)
->registerListeners() = 注册监听器(略)
-> finishBeanFactoryInitialization(beanFactory) = 创建Bean(重点)
-> finishRefresh() = 发布相应的事件(略)

第三层:obtainFreshBeanFactory() (重点1)
-> refreshBeanFactory() = 刷新BeanFactory(重点)
-> getBeanFactroy() = 获取BeanFactory(略)

第三层:finishBeanFactoryInitialization(beanFactory) (重点2)
-> beanFactory.setConversionService(…) = 配置类型转换服务(略)
-> beanFactory.addEmbeddedValueResolver(…) = 设置内嵌的值解析器(略)
-> beanFactory.getBeanNamesForType(LoadTimeWeaver…) 和 getBean(veaverAwareName) = 初始化LoadTimeWeaverAware(略)
-> beanFactory.setTmpClassLoader(null) = 禁止使用临时类加载器做类型匹配(略)
-> beanFactory.freezeConfiguration() = 配置冻结(略)
-> beanFactory.preInstantiateSingletons() = 实例化Bean(重点)

第四层:refreshBeanFactory() (重点1)
-> destroyBeans() = 销毁所有Bean(略)
-> closeBeanFactory() = beanFactory置null(略)
-> createBeanFactory() = 创建新的BeanFactory(略)
-> beanFactory.setSerializationId(getId()) = 设置序列化Id(略)
-> customizeBeanFactory(beanFactory) = 设置是否允许BeanDeifinition覆盖、是否允许循环引用(记下)
-> loadBeanDefinition(beanFactory) = 配置文件解析,标准化为BeanDefinition(重点)
-> this.beanFactory = beanFactory = 设置beanFactory,为后一个getBeanFactory服务(略)

第四层:beanFactory.preInstantiateSingletons() (重点2)
对于创建bean的过程这里做一个大概的描述,大家可以根据这个描述一层一层的debug查看:

-> 首先根据beanDefinitionNames获取RootBeanDefinition
-> 如果beanDefinition是单例的
-> 判断是否是FactoryBean

-> 如果是FactoryBean,根据BeanDefination的Name获取FactoryBean。注意,其中FactoryBean是对BeanFactroy的封装
-> 判断是否需要初始化
-> 如果需要则调用getBean(beanName)

->如果不是FactoryBean,调用getBean(beanName)

-> 对于getBean(beanName)方法可以进入看具体实现:
-> doGetBean(name, requiredType, args, typeCheckOnly)
-> 然后是真正的创建Bean的过程
-> createBean(beanName …)
-> doCreateBean(…)
-> createBeanInstance(…)
-> instantiateBean(…)
-> …instantiate(…)
-> BeanUtils.instantiateClass() = 反射创建Bean
-> instantiateWithMethodInjection() = cglib创建Bean
-> 到此,Spring Bean就成功创建出来了,当然在创建过程中可能会有一些附加的配置,但是这里只描述主线,有兴趣的同学可以在此基础上扩展。

第五层: loadBeanDefinition(beanFactory) (重点)
-> 由于涉及内容太多,同样只对主线做一个描述:
-> loadBeanDefinitions(beanDefinitionReader)
-> reader.loadBeanDefinitions(configResources)
-> loadBeanDefinitions(resource)
-> loadBeanDefinations(new EncodeResource(resource))
-> doLoadBeanDefinations(inputSource, encodeResource.getResource())
-> registerBeanDefinition(doc, resource)
-> documentReader.registerBeanDefinitions(doc, createReaderContext(resource))
-> doRegisterBeanDefinitions(doc.getDocumentElement())
-> parseBeanDefinitions(root, this.delegate)
-> delegate.parseCustomElement(ele)
-> parseCustomElement(ele, null)
-> handler.parse(ele, new ParseContext(this.readerContext, this, …))
-> parser.parse(element, parseContext)
-> parseInternal(element, parseContext)

以上是对主线代码的一次追踪,但是由于代码量实在太大,这个过程也只是辅助不要迷失在debug的循环之中,许多细节的地方需要自己去摸索。最后希望大家共同努力,共同进步。

更多信息,请关注公众号:
在这里插入图片描述