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