1.源码复习前,概要
ApplicationContext的顶级接口为BeanFactory,其下的ConfigurableApplicationContext扩展了 refresh(),close()等方法,使其具备刷新 、关闭上下文的能力
ApplicationContext:应用上下文,Bean的创建,管理等核心功能实际上还是由BeanFactory进行的
***重点核心 refresh() 方法
1.prepareRefresh()
a.刷新前的准备工作,实际上就是创建Environment环境变量,并赋值给environment属性,环境组件主要用于加载jvm中k-v参数,系统变量k-v参数,我们
自定义的properties,yaml等文件,Environment的resolvePlaceholders(),可以对${},#{}等表达式进行解析,不同表达式可能需要对应的解析类来进行辅助解析
b.initPropertySources(),扩展方法,提供给子类实现,初始化上下文环境中的任何占位符资源
2.ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
a.判断当前AbstractRefreshableApplicationContext的beanFactory属性是否为空,不为空则销毁所有单例bean,并将beanFactory赋值为null,否则
new 一个 DefaultListableBeanFactory对象,设置序列化id,customizeBeanFactory(beanFactory)进行一些定制操作(是否允许bean定义信息的重写
、循环引用),loadBeanDefinitions()加载bean的定义信息(通过不同的实现类,注解方式,xml方式,扫描方式...)并放入DefaultListableBeanFactory
的beanDefinitionMap属性内,其是一个concurrentHashMap,将beanFactory赋值给AbstractRefreshableApplicationContext类的beanFactory属性
3.prepareBeanFactory(beanFactory)
a.beanFactory在此上下文使用的前置准备工作,bean类加载器、bean表达式解析器、属性编辑注册器的设置,个别bean后置处理器的加载ApplicationContextAwareProcessor
该后置处理器主要用于实现了xxxAware接口bean的处理,为其赋值底层组件
b.设置一些忽略的依赖接口,注解一些beanFactory可解析的依赖类型,添加ApplicationListenerDetector容器监听类的探测器,用于发现ApplicationListener
c.最终判断容器内有没有Environment、SystemProperty、SystemEnvironment等类型bean,没有的话进行默认注册
4.postProcessBeanFactory(beanFactory);
a.允许在上下文子类中对beanFactory进行后处理,其是一个扩展方法!!!
5.invokeBeanFactoryPostProcessors(beanFactory);
a.调用工厂的后处理器,在上下文中注册为bean,如果上下文中存在bean工厂的后置处理器优先调用BeanDefinitionRegistry的BeanDefinitionRegistryPostProcessor
进行beanFactory的后处理postProcessBeanDefinitionRegistry()
b.注意此处不初始化FactoryBean,我们需要保留所有常规bean未初始化以让bean工厂后处理器应用于他们,接下来根据接口优先级进行处理,首先处理实现了PriorityOrdered接口
的进行后处理器排序添加进registryProcessors链表集合,调用后处理器的postProcessBeanDefinitionRegistry应用于beanFactory
c.与b的处理流程相似,Ordered接口的,最终调用剩下的BeanDefinitionRegistryPostProcessors流程也一致
d.现在调用目前未知所有beanFactory后处理器的postProcessBeanFactory方法,包含BeanDefinitionRegistryPostProcessor和非BeanDefinitionRegistryPostProcessor类型
的beanFactory后处理器
e.最后重复执行上述操作,避免遗漏,clearMetadataCache()清除缓存的合并bean定义,因为后处理器可能修改了元数据,例如替换值中的占位符
f.检测到LoadTimeWeaver并准备编织,如果同时找到(例如,通过ConfigurationClassPostProcessor注册的@Bean方法)
6.registerBeanPostProcessors(beanFactory)
a.注册拦截bean创建的bean处理器,首先获取beanFactory内BeanPostProcessor类型,允许多例,不允许早期初始化的所有后置处理器名称
b.注册一个BeanPostProcessorChecker他会在bean后置处理实例化期间创建bean时记录消息,即当bean没有资格被所有BeanPostProcessor
处理时
c.根据优先级先后将BeanPostProcessor进行注册(到beanFactory中)首先注册实现了PriorityOrdered接口,接着Ordered接口,最后rugular常规
bean后置处理,分别都会进行排序并注册到beanFactory中
d.每个优先级处理中都会保存实现了MergedBeanDefinitionPostProcessor的bean后置处理器到internalPostProcessors的ArrayList集合中
e.注册所有保存MergedBeanDefinitionPostProcessor合并bean定义信息的后处理器(先会排序)
f.最后注册ApplicationListenerDetector发现容器监听ApplicationListener的后处理器,其实现了DestructionAwareBeanPostProcessor(销毁感知bean的后处理器),MergeBeanDefinitionPostProcessor
7.initMessageSource()
a.为上下文初始化消息源,获取beanFactory对象,判断内部有没有MessageSource类型的bean,有则判断当前消息源是否是分层消息源HierarchicalMessageSource,以及当前AbstractApplicationContext的
parent属性也就是父组件不能为空,通过分层消息源获取父消息源时,如果父消息源尚未注册,则仅将父上下文设置为父消息源
b.为空则创建一个DelegatingMessageSource委托消息源,设置ParentMessageSource为父组件的消息源或父组件,接着在BeanFactory中进行注册
8.initApplicationEventMulticaster
a.为此上下文初始化事件多播器,查看beanFactory内有没有事件多播器的定义信息,有的话直接获取赋值,没有的话,创建一个SimpleApplicationEventMulticaster
赋值给当前AbstractApplicationContext的applicaitonEventMulticaster属性,并将其注册到beanFactory中
9.onRefresh
a.初始化特定上下文中的其他特殊bean,是一个扩展方法,用于初始化特有组件bean的,参考SpringMVC中扩展实现onRefresh方法,进行了九大组件的初始化
10.registerListeners
a.检查监听器bean并注册他们,获取容器内的所有监听类,添加到事件多播器中,首先注册静态监听的多播器,最后使用多播器进行早期事件的派发,同步/异步
方式进行事件派发,具体参考Executor是否为空,Executor实际就是一个维护了任务属性的单例线程池,默认为null
11.finishBeanFactoryInitialization(beanFactory)
a.实例化所有剩余的单例bean,开始初始化转换服务ConversionService用于常规参数到对象属性的类型转换,如果beanFactory中不包含内嵌的值解析器
则注册一个StringValueResolver值解析器,实际原理就是将值交给Enviroment的resolvePlaceHolders 解析占位符方法进行解析返回,初始化LoadTimeWeaverAwareBean,以便尽早注册他们的转换器
设置临时类加载器,冻结配置,此时配置无法修改,接下来实例化所有的剩余(非惰性)单例
b.获取所有bean定义名称封装到ArrayList集合中,遍历,将所有beanName封装成RootBeanDefinition(Spring中对于bean的高度抽象),判断其
非抽象,是单例,非懒加载后,判断其是否是一个FactoryBean工厂bean,如果是工程bean通过在bean名称前+&获取实际对象最终返回最终在单例池中存入他的getObject()方法的实例
中间还穿插着是否立即初始化等判断(isEagerInit)如果不是直接调用DefaultListableBeanFactory的getBean方法传入bean名称
c.getBean方法内部调用doGetBean(name, null, null, false),首先获取转换后的bean名称,bean处理id属性标识外还有name属性,这里就是获取我们name属性值(aliasMap中获取),如果name不能空就用name值,否则就是id值
首先从三级缓存中拿值,getSingleton(beanName, true)传入要获取的bean名称和允许早期引用,一级缓存中拿到直接返回,为空的话判断是否是一个正在创建中的单例bean,是的话从二级缓存中拿,二级缓存也没拿到则判断,是否允许早期引用
从三级缓存中拿,通过beanName去调用三级缓存的ObjectFactory的getObject()方法进行获取,如果都没获取到则返回为空 null
d.三级缓存中如果不为null则会进入getObjectForBeanInstance()方法内的判断,第一个判断isFactoryDereference(name)判断是否是要获取工厂bean本身而非其getObejct()返回对象,如果是要获取工厂bean本身下个判断直接返回,否则从工厂bean的缓存中
尝试拿取,为空将三级缓存中获取的bean封装成FactoryBean,尝试通过bean名称获取合并的bean定义信息,最后getObjectFromFactoryBean方法中获取工厂bean中getObject()方法返回值,并存入factoryBeanObjectCache(工厂bean对象缓存)最终返回
此方法,主要用于工厂bean的判断,如果不是工厂bean或者需要获取工厂bean(FactoryBean)本身,则会直接返回
e.三级缓存没拿到的情况,首先判断isPrototypeCurrentlyInCreation(beanName)查看我们当前对象是否是正在创建的原型,通过NamedThreadLocal存储正在创建的原型对象,命名线程本地变量,说明正在创建的原型对象是与线程绑定的,同一线程内获取的都是
唯一,(curVal != null &&(curVal.equals(beanName) || (curVal instanceof Set && ((Set<?>) curVal).contains(beanName)))) 判断条件成立说明当前可能处于循环引用中,抛出异常BeanCurrentlyInCreationExcepton(bean当前正在创建异常),假设这么
一个场景A构造依赖B,B构造依赖A,因为无法实例化所有不考虑三级缓存,A 在 确定构造参数,实例化 进行依赖解析 (具体参考DefaultListableBeanFactory中resolveDependency方法)发现依赖B回调doCreateBean方法此时无法从三级缓存拿到,因为A并没有实例
化完成,B也走到A这一步进行依赖解析,发现需要A,回调doCreateBean()方法,这时我们这个判断就会抛出异常
f.获取父级bean工厂,如果此工厂不为空同时当前工厂中不包含这个bean定义信息则去检查父级中是否存在等等。。。
g.markBeanAsCreated()方法,将bean标记为已创建,实际就是存储在alreadyCreated这个set集合中,并清除对应的合并bean定义信息,因为bean已经在创建中了就在后续对bean定义重新合并以防万一他的一些元数据发生改变
h.接下来获取合并bean定义信息,检查他是否是抽象的如果是则抛出异常BeanIsAbstractException,获取当前bean所依赖的bean名称(dependsOn,依赖不等于引用,A依赖B但A不一定要用B,A引用B则A一定要用B),下面一系列关于DependsOn的处理只是为了确保
当前bean所依赖的bean在当前bean之前完成初始化,其中穿插着是否循环依赖等的判断,最后回调getBean(dep)去完成初始化
i.来到了创建bean实例的部分,首先判断当前RootBeanDefinition是否是单例的,调用getSingleton方法,参数2为ObjectFactory使用lambda表达式回调createBean方法,进入getSingleton方法内部,首先从单例池中尝试获取beanName对应的对象,beforeSingletonCreation()
方法进行检查判断,当前创建bean要是正在创建中的,不在创建检查排除范围内的singletonObject = singletonFactory.getObject();回调上述说的ObjectFactory对象lambda表达式中的createBean方法
j.Object bean = resolveBeforeInstantiation(beanName, mbdToUse) 在对象实例化前,给予机会返回一个代理对象,通过bean后置处理器InstantiationAwareBeanPostProcessor的实现类进行完成(详情了解Aop底层)
Object beanInstance = doCreateBean(beanName, mbdToUse, args) 进入该方法内部,instanceWrapper = createBeanInstance(beanName, mbd, args) 此处完成bean对象的创建,具体流程可以自行查看,穿插了各类检查,FactoryBean方法判断及调用,确认构造方法,
AutowiredConstructor自动注入构造参数,构造参数解析器(可以自行去了解)....
k.applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName) 应用MergedBeanDefinitionPostProcessor后置处理器,可以在流程此处对bean定义信息进行修改,boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&isSingletonCurrentlyInCreation(beanName));
早期单例暴露,实际就是将bean缓存进三级缓存,以便及时在由BeanFactoryAware等生命周期接口触发时也能对循环引用进行解析addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean)) 方法getEarlyBeanReference参考自动代理创建器AnnotationAwareAspectJAutoProxyCreator
其内部getEarlyBeanReference方法中wrapIfNecessary(如有必要进行包装)方法
l.populateBean(beanName, mbd, instanceWrapper)方法对bean的属性进行填充,中间会进行bean属性引用的解析针对于不同的方式参考实现也不尽相同,当依赖的属性存在于beanFactory的定义中时会回调getBean方法将属性名作为beanName传入
applyPropertyValues(beanName, mbd, bw, pvs)方法中应用属性值
n.exposedObject = initializeBean(beanName, exposedObject, mbd) 初始化bean,invokeAwareMethods方法针对于Aware下子接口的一些判断处理,wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName) 应用bean后置处理器的初始化方法前处理,invokeInitMethods(beanName, wrappedBean, mbd)
调用初始化方法,wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName) 调用初始化方法之后的处理,Object earlySingletonReference = getSingleton(beanName, false) 与下方判断中的exposedObject = earlySingletonReference 主要是针对循环引用情况 1.避免二级缓存对象残留 2.下方判断主要是因为 bean初始化方法后的后处理中
可能返回代理对象,所以需要拿初始化后对象和原始对象进行比较判断初始化后处理中是否进行了代理,如果没有,而我们的二级缓存中又拿到了对象,则需要确保我们返回的最终对象是二级缓存中的,因为二级缓存配合三级缓存中value值ObjectFactory的lambda中getEarlyBeanReference方法可以确保在循环引用中代理的注入,后面就是一些一次性操作就是为单例bean注册一个销毁回调
方便容器关闭时对bean的销毁,返回来到DefaultSingletonBeanRegistry的getSingleton方法接收返回的bean对象,将newSingleton = true ,addSingleton(beanName, singletonObject)添加到一级缓存中this.singletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
this.earlySingletonObjects.remove(beanName);
this.registeredSingletons.add(beanName);
一个bean经过上述步骤就创建并放入单例缓存池中成功(多例对象prototype参考AbstractBeanFactory中mbd.isPrototype()判断内的实现)
12.finishRefresh()
a.最后一步,发布相应的事件 clearResourceCaches() 清除上下文中的缓存资源(例如扫描中的ASM元数据)initLifecycleProcessor() 初始化生命周期处理器
getLifecycleProcessor().onRefresh() 将刷新成功事件传播到生命周期处理器 publishEvent(new ContextRefreshedEvent(this)) 发布容器刷新完毕事件
LiveBeansView.registerApplicationContext(this) 如果处于活动状态参与LiveBeansView MBean
至此原理简单过了一遍