Spring容器
2021-04-13 21:39:36 0 举报
AI智能生成
Spring容器初始化的源码分析
作者其他创作
大纲/内容
AbstractApplicationContext是Spring容器的模板抽象类,ApplicationContext实现都继承了它。
实现接口
ConfigurableApplicationContext
ApplicationContext
ListableBeanFactory<br>支持根据条件查找一批bean而非一个bean
BeanFactory<br>提供了一个基本的bean容器视图<br>
HierarchicalBeanFactory<br>提供容器层级支持,在本容器的操作也将检查父容器<br>支持重写父容器的bean
BeanFactory<br>提供了一个基本的bean容器视图<br>
EnvironmentCapable<br>获取环境配置,ConfigurableApplicationContext收窄了返回类型ConfigurableEnvironment
MessageSource<br>消息处理,提供消息的参数化和国际化处理
ApplicationEventPublisher<br>提供事件发布的支持,驱动事件监听
ResourcePatternResolver<br>使用表示资源路径的字符串来加载多个资源<br>提供classpath*前缀支持,支持通配符
ResourceLoader<br>使用标识资源路径的字符串来加载单个资源<br>提供classpath前缀支持<br>AAC继承了这个接口的实现类DefaultResourceLoader
Lifecycle<br>定义启停生命周期控制,典型用于控制异步处理<br>它只作用于顶级的单例bean<br>SmartLifecycle提供更复杂的功能支持<br>
Closeable<br>JDK提供的接口,用于关闭时释放资源等处理<br>Spring容器中持有的bean可能包含资源的释放,<br>都会在该接口实现中统一调用<br>
AutoCloseable<br>支持try-resource语法
简介
AC的抽象实现。不关注配置的存储类型;简单地实现了通用的容器功能。使用了模板方法设计模式,需要实体子类实现抽象方法。
和普通的BF相比,AC需要探测定义在内部BF中的一些特殊bean。该类自动注册了定义在容器中的BeanFactoryPostProcessor,BeanPostProcessor,ApplicationListener
可以配置bean名称为"messageSource"的MessageSource来处理消息;否则,消息的解析将委托给父容器。<br>可以配置bean名称为"applicationEventMulticaster"的ApplicationEventMulticaster来分发应用事件;否则,默认配置SimpleApplicationEventMulticaster<br>
继承了DefaultResourceLoader来实现资源的加载。
核心方法
refresh
prepareRefresh();<br>刷新上下文前准备
this.closed.set(false);<br> this.active.set(true);<br>设置AC状态
initPropertySources();<br>钩子方法:在上下文环境中指定初始化占位符属性源
getEnvironment().validateRequiredProperties();<br>验证所有标记为必须的属性都可以解析。<br>ConfigurablePropertyResolver#setRequiredProperties<br>
earlyApplicationListeners如果不为null,那么里面存的就是在pre-refresh之前注册到AC的监听器,只要调用过refresh方法就不会为null。<br>earlyApplicationEvents如果不为null,说明监听器还没有注册到applicationEventMulticaster,里面暂存的事件会等到监听器注册完毕后进行处理,处理完成后会置为null<br>
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();<br>告诉子类刷新内部的BF,并返回刷新后的BF。内部调用两个方法都是抽象方法,待子类实现。
refreshBeanFactory();
return getBeanFactory();
prepareBeanFactory(beanFactory);<br>预处理BF,进行一些默认配置
beanFactory.setBeanClassLoader(getClassLoader());<br>设置BF使用上下文的类加载器
if (!shouldIgnoreSpel) {<br> beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));<br> }<br>如果没有忽略SpEL,设置SpEL作为默认的表达式解析器
beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));<br>新增PropertyEditor
通过注册BeanPostProcessor,来处理这些接口的回调<br>ignoreDependencyInterface:自动装配时忽略给定的依赖接口,这通常用于AC来注册通过其他方式解析的依赖。<br>例如BF通过BeanFactoryAware,AC通过ApplicationContextAware。默认只有BeanFactoryAware接口被忽略。
registerResolvableDependency:注册一个特殊的依赖类型及其关联的自动装配值。这用于容器引用,它们可以被自动装配却没有在<br>工厂中定义为bean.
通过注册BeanPostProcessor,来处理注册inner bean中的单例的ApplicationListener
探测加载时织入器,加载时织入可以通过在加载类字节码时更改字节码,来增强类的行为。
注册默认的环境bean:environment,systemProperties,systemEnvironment,applicationStartup
准备工作执行完毕,进入初始化阶段,try-catch
postProcessBeanFactory(beanFactory);<br>钩子方法,让子类注册BeanFactoryProcessor
invokeBeanFactoryPostProcessors(beanFactory);<br>调用容器中注册的BeanFactoryPostProcessor。<br>BFPP执行时,所有的bean都加载了,但是没有初始化。<br>这允许BFPP可以在初始化bean前给bean更改或增加属性<br>
PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());<br>调用BFPP的postProcessBeanFactory方法。该方法中提到了两种BFPP:BeanDefinitionRegistryPostProcessor和BeanFactoryPostProcessor。<br>后者是通常的BFPP,前者扩展了后者,多定义了方法postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry),它允许在执行下<br>一步postProcessBeanFactory之前对bean定义注册表进行操作,包括新增bean定义。<br>
STEP 1<br>如果当前的BF实现了BeanDefinitionRegistry,那么需要额外处理BeanDefinitionRegistryPostProcessor<br>1. 处理AC传过来的beanFactoryPostProcessors,调用它们的postProcessBeanDefinitionRegistry方法<br>2. 处理BF中注册为Bean的BeanDefinitionRegistryPostProcessor<br> a. 处理匹配PriorityOrdered接口的,先排序再处理<br> b. 处理匹配Ordered接口的,先排序再处理<br> c. 处理其他的,由于在上述处理过程中可能向BF中注册了新的BDRPP,所以要不断地检查,直到没有新的BDRPP产生。<br>3. 调用所有BFPP(和BDRPP)的postProcessBeanFactory方法<br><br>如果当前的BF没有实现BeanDefinitionRegistry,那么直接处理AC传过来的beanFactoryPostProcessors<br>调用它们的postProcessBeanFactory方法<br>
STEP 2<br>处理BF中注册为Bean的BFPP<br>a. 处理匹配PriorityOrdered接口的,先排序再处理,调用它们的postProcessBeanFactory方法<br> b. 处理匹配Ordered接口的,先排序再处理,调用它们的postProcessBeanFactory方法<br>c. 处理其他的,调用它们的postProcessBeanFactory方法<br>
registerBeanPostProcessors(beanFactory);<br>将BPP注册到BF,便于在初始化Bean时对Bean进行处理
PostProcessorRegistrationDelegate.registerBeanPostProcessors(beanFactory, this);<br>将BPP注册到BF
处理BF中注册为Bean的BPP<br>1. 首先注册BeanPostProcessorChecker,用于打印日志<br>2. 注册匹配PriorityOrdered接口的,先排序再注册<br>3. 注册匹配Ordered接口的,先排序再注册<br>4. 注册其他BPP<br>5. 将实现了MergedBeanDefinitionPostProcessor的BPP重新注册,先排序再注册<br>6. 重新注册ApplicationListenerDetector
重新注册会先移除,再注册,所以重新注册是为了保证BPP的执行顺序
initMessageSource();<br>注册messageSource,确保有messageSource存在
initApplicationEventMulticaster();<br>注册applicationEventMulticaster,确保有applicationEventMulticaster存在
onRefresh();<br>钩子方法,允许子类初始化其他特殊的Bean
registerListeners();<br>注册监听器,并发布早期应用事件
1 将监听器注册到applicationEventMulticaster<br> AC中注册的监听器+BF中注册为bean的监听器ApplicationListener<br>2 将早期产生的事件交给applicationEventMulticaster处理
finishBeanFactoryInitialization(beanFactory);<br>实例化所有剩余的(非延迟初始化)单例
1 如果有则设置并初始化转换服务conversionService<br>2 如果BF中没有内置的valueResolver,设置默认的valueResolver<br>3 初始化LoadTimeWeaverAware bean使它们尽早注册transformer<br>4 不再使用临时的用于类型匹配的类加载器<br>5 锁定配置,不允许再对bean定义做修改<br>6 实例化所有剩余的(非延迟初始化)单例
beanFactory.preInstantiateSingletons();
AbstractBeanFactory#getBean
AbstractBeanFactory#doGetBean
DefaultSingletonBeanRegistry#getSingleton 三级缓存查找
DefaultSingletonBeanRegistry#getSingleton(String beanName, ObjectFactory<?> singletonFactory)
ObjectFactory#getObject
AbstractAutowireCapableBeanFactory#createBean
AbstractAutowireCapableBeanFactory#doCreateBean
AbstractAutowireCapableBeanFactory#createBeanInstance
AbstractAutowireCapableBeanFactory#addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean)); 暴露早期bean,解决环形依赖
AbstractAutowireCapableBeanFactory#populateBean
autowire -> getBean
AbstractAutowireCapableBeanFactory#initializeBean
DefaultSingletonBeanRegistry#addSingleton(beanName, singletonObject);
finishRefresh();<br>初始化LifecycleProcessor并调用它的onRefresh方法<br>发布ContextRefreshedEvent事件
1 清除资源缓存<br>2 初始化lifecycleProcessor确保它存在<br>3 调用lifecycleProcessor的onRefresh方法<br>4 发布ContextRefreshedEvent
try结束,如果在上述过程中发生异常
destroyBeans();<br>销毁在BF中初始化的缓存单例
cancelRefresh(ex);<br>重置active标志位false
进入finally<br>清除掉Spring中公共的内省缓存,<br>因为不再需要单例bean的元数据了
close<br>调用doClose,并移除不再需要的已注册的JVM shutdownHook<br>
doClose
1 如果AC可用并且没有关闭,执行关闭操作<br>2 发布ContextClosedEvent事件<br>3 调用lifecycleProcessor的onClose方法<br>4 销毁在BF中初始化的缓存单例<br>5 调用onClose钩子方法,让子类执行一些清理工作<br>6 将监听器恢复到容器准备刷新的状态<br>7 将容器设置为未激活this.active.set(false);
Runtime.getRuntime().removeShutdownHook(this.shutdownHook);
DefaultListableBeanFactory
DefaultListableBeanFactory作为ApplicationContext的默认底层容器实现
继承父类和实现接口
AbstractAutowireCapableBeanFactory<br>#createBean
AbstractBeanFactory<br>#doGetBean
FactoryBeanRegistrySupport<br>支持用FactoryBean创建的单例注册<br>集成了父类DSBR的单例管理功能<br>
DefaultSingletonBeanRegistry<br>#getSingleton 单例bean三级缓存。<br>使用ObjectFactory来解决环形依赖问题<br>
SimpleAliasRegistry<br>使用ConcurentHashMap实现的别名注册表<br>别名 -> 规范名称。别名作为key不可以重复。
AliasRegistry<br>定义别名的注册表<br>包含注册和获取bean的别名
SingletonBeanRegistry<br>定义共享单例bean的注册表<br>包含注册和获取单例bean等方法
ConfigurableBeanFactory<br>配置接口,提供配置BF的能力
HierarchicalBeanFactory
BeanFactory
SingletonBeanRegistry
AutowireCapableBeanFactory<br>提供自动装配的能力
BeanFactory
ConfigurableListableBeanFactory
ListableBeanFactory...
AutowireCapableBeanFactory...
ConfigurableBeanFactory...
BeanDefinitionRegistry
AliasRegistry
Serializable
核心方法
preInstantiateSingletons<br>用来初始化容器中注册的单例bean
遍历bean定义,如果是单例且不是懒加载就调用getBean(String name)方法创建和初始化bean<br>AbstractBeanFactory#doGetBean<br>
1 解析bean的真名<br>去掉表示factoryBean的名称前缀&<br>通过别名注册表查询真名
2 查找缓存中是否包含该单例bean<br>DefaultSingletonBeanRegistry#getSingleton(String beanName)<br>
三级缓存查找:singletonObjects里面是初始化完成的单例bean;earlySingletonObjects里面是正在创建,已实例化但未初始化的bean引用,用于解决环形依赖;singletonFactories用于获取earlySingleton的工厂,只使用一次,使用完成后就移除,将生成的对象放到二级缓存中。
3 如果返回的bean不为空<br>调用getObjectForBeanInstance取得bean实例<br>
1 如果doGetBean传进来的名称标识了它是FactoryBean(&打头),并且返回的单例bean就是FB,那么直接返回
2 如果返回的bean不是FB,直接返回
3 先从由FBRS缓存中获取,若取到了就直接返回<br>FactoryBeanRegistrySupport#getCachedObjectForFactoryBean<br>
4 若没有取到,就要通过FB创建<br>如果通过bean真名查找到了Bean定义,且Bean定义是合成的就不执行BPP<br>FactoryBeanRegistrySupport#getObjectFromFactoryBean<br>
如果FB配置是单例的并且DefaultSingletonBeanRegistry缓存中已经存在了bean真名代表的单例<br>1 尝试从FBRS的缓存中取,取到了就返回<br>2 没有取到,就调用FB的getObject方法,再次检查FBRS的缓存<br> a 如果取到了,就代表在getObject方法调用过程中已经将该Bean加入了FBRS的缓存(在环形依赖的情况下会发生),返回从缓存中取到的值<br> b 如果没取到,就代表这是首次从该FB获取单例,根据方法参数条件判断是否执行BPP。<br>如果参数表示需要执行BPP<br> ① 如果该bean真名代表的单例还在创建中,那么直接临时返回该对象。即不缓存也不执行BPP<br> ② 先执行beforeSingletonCreation回调 -> 执行BPP(AbstractAutowireCapableBeanFactory#postProcessObjectFromFactoryBean) -> 执行afterSingletonCreation回调(为什么回调是包在执行BPP周围)<br> 检查DSBR缓存中是否存在该bean真名,如果不存在就加入缓存(可能在执行getObject过程中移除了DSBR中的该bean)
否则,就直接调用FB的getObject方法,再根据方法参数条件判断考虑是否执行BPP。
4 如果返回的bean为空
1 检查Bean定义是否存在,如果找不到且有父容器,则委托给父容器处理并返回
2 Bean定义在该容器存在
1 如果不只是为了检查类型,那么标记该bean真名为已创建
2 获取Bean定义中该bean的依赖bean,遍历它们<br> a 检查循环依赖,出现循环依赖报错<br> b 将依赖关系注册到dependentBeanMap和dependenciesForBeanMap<br> c 初始化依赖bean
3 如果Bean定义配置为单例,创建bean实例<br>DefaultSingletonBeanRegistry#getSingleton(String beanName, ObjectFactory<?> singletonFactory)<br>
1 检查singletonObjects缓存中是否存在该bean,若存在直接返回<br>
2 不存在,则准备创建。beforeSingletonCreation回调 -> 调用ObjectFactory#getObject -> afterSingletonCreation回调
这里传入的ObjectFactory是一个匿名内部类,里面调用了AbstractAutowireCapableBeanFactory#createBean实现<br>createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)<br>
1 调用resolveBeforeInstantiation 给BeanPostProccessors一个机会返回一个代理实例而不是目标bean实例<br>得到的返回值不为null则直接返回。只调用InstantiationAwareBeanPostProcessor的postProcessBeforeInstantiation来尝试创建bean,<br>创建成功之后,会应用所有的BPP的postProcessAfterInstantiation
2 调用doCreateBean
createBeanInstance<br>创建Bean实例,并使用BeanWrapper包装
Supplier<?> instanceSupplier = mbd.getInstanceSupplier();<br> if (instanceSupplier != null) {<br> return obtainFromSupplier(instanceSupplier, beanName);<br> }<br>尝试从supplier获取Bean实例
if (mbd.getFactoryMethodName() != null) {<br> return instantiateUsingFactoryMethod(beanName, mbd, args);<br> }<br>尝试从工厂方法获取Bean实例
尝试用合适的构造器构造实例
applyMergedBeanDefinitionPostProcessors<br>遍历调用MergedBeanDefinitionPostProcessor#postProcessMergedBeanDefinition<br>允许在设置属性前,修改bean定义
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));<br>如果允许环形引用,则注册单例工厂到DSBR第三级缓存<br>
populateBean(beanName, mbd, instanceWrapper);
遍历执行InstantiationAwareBeanPostProcessor#postProcessAfterInstantiation。在调用工厂方法或构造器初始化bean之后,在设置属性之前的扩展点。
执行自动装配,将装配结果放到PropertyValues中,后面就是来操作它了
遍历执行InstantiationAwareBeanPostProcessor#postProcessProperties
依赖检查
类型转换以适配属性类型,之后将操作后的属性值设置到实例中,完成bean装配
initializeBean(beanName, exposedObject, mbd);
invokeAwareMethods(beanName, bean);
BeanPostProcessor#postProcessBeforeInitialization
invokeInitMethods(beanName, wrappedBean, mbd);
((InitializingBean) bean).afterPropertiesSet()
invokeCustomInitMethod(beanName, bean, mbd)
BeanPostProcessor#postProcessAfterInitialization
3 如果是通过getObject方法创建的新单例,那么将单例放到singletonObjects缓存中。
场景问题
Spring如何解决环形依赖
Spring使用三级缓存来解决环形依赖,三级缓存在DefaultSingletonBeanRegistry中,它们是三个map
singletonObjects:里面存放的是初始化完成的Bean
earlySingletonObjects:里面存放着通过singletonFactories调用getBean返回的结果
singletonFactories:里面存放着仅用于获取earlySingleton的工厂ObjectFactory,当发生环形依赖时,就会通过该工厂调用一次getObject获取尚未完全装配完成的Bean。调用完成后,将尚未初始化完成的返回对象放到earlySingletons二级缓存中,而该ObjectFactory将从三级缓存中移除
解决方案不支持
构造器注入循环依赖
prototype模式field属性注入循环依赖
可参考文章:https://blog.csdn.net/fedorafrog/article/details/104550165
收藏
收藏
0 条评论
下一页