总概
最近始终在思考Spring的设计,从这个角度去思考这个框架,并且散发思考其余Spring的生态。而Spring的根底就是Bean的生命周期的治理,由此去合并AOP的性能,同时还有配置的治理,事件监听的治理,还有MessageSource的治理,还有资源的治理,等等散发开来。咱们先从Spring的Bean的生命周期这个角度去思考Spring的设计。
Spring容器生命周期
咱们在思考Spring的Bean的生命周期之前须要站在更上一层,Spring的容器生命周期去思考能力有一个残缺的大局观。说到这个大局观,咱们须要对Spring的容器的接口定义须要相熟一下,同时也须要相熟一下接口的实现的骨架,最初面去关注外围的几点,汇集了解Spring的Bean生命周期。
Bean的生命周期咱们须要从这个角度去思考,首先咱们须要将Bean进行配置化,能够通过配置去批改Bean的值,所以咱们须要构建好Environment。之后咱们须要把Bean的定义依照规定发现扫描,而后存储起来供前期实例化Bean应用。最初咱们开始Bean的生命周期的流转,而对于一个框架来说须要对每一步能够提供能够拓展的接口,包含实例化前后,初始化前后,以此能够更好拓展Bean的治理,以及能够供第三方接入Bean治理。
Spring的容器接口
咱们这里做一些简略的介绍。首先是和咱们生产应用相干的是
web相干接口:ConfigurableWebApplicationContext和WebApplicationContext。
外围接口:
- EnvironmentCapable:提供获取Environment接口
ListableBeanFactory/BeanFactory:提供Bean依赖查找。
至于其余的接口不是咱们聚焦的外围,能够自行查看。
Spring的容器实现
咱们以更多应用的java配置web容器相干的一个具体实现举例:AnnotationConfigWebApplicationContext
对于应用模板办法设计模式相熟的小伙伴,肯定比拟相熟这类写法,而咱们次要的办法的外围实现在AbstractApplicationContext#refresh办法,该办法就是容器启动的生命周期,包含如下:
- 筹备Environment
- 获取刷新之后的BeanFactory
- 筹备实例化之后的BeanFactory
- BeanFactory的后置解决拓展办法
- 执行BeanFactory的后置处理器BeanFactoryPostProcessor。这外面其中就有是BeanDefinition的扫描的拓展
- 注册Bean的后置处理器BeanPostProcessor。这外面更多是一些依赖注入的后置处理器
- 初始化messageSource
- 初始化事件播送器,用于事件监听器
- onRefresh拓展办法
- 注册监听器
- 实现BeanFactory的初始化。这外面有Bean的生命周期的治理
- 实现刷新
Spring的生命外围
咱们会去除一些监听器治理和资源管理等等这些其余性能的治理,以此更加聚焦的思考Bean的生命周期。去除之后的外围的容器的生命周期外围为以下几点:
- Environment的治理
- BeanDefinition的治理
- Bean的生命周期
Environment治理
把Environment领进去是因为咱们在加载BeanDefinition的时候须要这些配置,这一块的拓展也能够联合咱们配置核心加以举例。
BeanDefinition治理
而对于BeanDefinition的治理,咱们以Java配置进行举例。BeanDefinition的治理接口是BeanDefinitionRegistry,会将BeanDefinition存储在容器内,供前期治理Bean的生命周期应用。
那么进一步去理解BeanDefinition的治理,咱们须要理解触发条件的治理,其中这些是由BeanFactory的后置处理器进行拓展管制,次要是以下步骤:
- BeanFactory的后置处理器ConfigurationClassPostProcessor的加载
- BeanFactory的后置处理器ConfigurationClassPostProcessor的执行
- BeanDefinition的扫描
- BeanDefinition的注册
加载
ConfigurationClassPostProcessor的加载是在获取刷新BeanFactory曾经注册作为BeanDefinition的定义
执行
ConfigurationClassPostProcessor的执行也是在容器执行BeanFactory的后置处理器会依据之前加载的后置处理器的BeanDefinition进行实例化,加载到容器外部,而后执行
扫描
BeanDefinition的扫描,首先是从BeanDefinition的名字进行判断外面的@Configuration的定义。而后应用ConfigurationClassParser#parse解析@Configuration配置的类,将外面的注解进一步解析包含@PropertySources、@ComponentScan、@ComponentScans、@Import、@ImportResource、@Bean
注册
ConfigurationClassParser解析配置类的注解收集好信息,进一步应用ConfigurationClassBeanDefinitionReader#loadBeanDefinitions进行注册BeanDefinition
Bean的生命周期
之前咱们扫描完BeanDefinition之后,而后就能够进行Bean的整个生命过程,而Bean的生命开始个别都是走依赖查找的办法AbstractBeanFactory#doGetBean,咱们以单例为例子,其余scope不进行赘述,次要有以下步骤:
- 从单例缓存中获取,同时对FactoryBean进行解决
- 从父容器进行依赖查找
- 对Bean的DependsOn有优先级须要依赖的Bean先依赖查找
- 单例进行实例化前置解决的拓展执行InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation如果返回不为null的实例,则不进行往下执行
- 依据反射进行实例化
- 执行合并BeanDefinition,执行MergedBeanDefinitionPostProcessor#postProcessMergedBeanDefinition
- 如果容许循环依赖,则先存储Bean实例化的Factory,用于循环依赖执行获取晚期的Bean
- 填充Bean,进行执行实例化之后的后置处理器,InstantiationAwareBeanPostProcessor#postProcessAfterInstantiation
- 填充Bean,执行属性后置处理器,InstantiationAwareBeanPostProcessor#postProcessProperties
- 初始化Bean,执行Aware前期处理器,比方BeanNameAware、BeanClassLoaderAware、BeanFactoryAware
- 初始化Bean,初始化之前的后置处理器
- 初始化Bean,执行初始化办法,包含自定义
- 初始化Bean,初始化之后的后置处理器
- 将单例进行存储缓存
依赖注入
以@Resource和@Autowire举例。而这两个解决都是以BeanPostprocessor进行拓展,首先须要将须要注入的信息进行扫描,应用InjectedElement进行存储,而后依据不同的状况进行注入。
@Resource注入
应用CommonAnnotationBeanPostProcessor处理器拓展。
- buildResourceMetadata办法扫描该办法外面标注@Resource等注解的属性或者办法
- @Resource的元素的注入进行复写应用getResource-》autowireResource进行依赖查找
- 默认调用beanFactory.resolveBeanByName依据名字进行依赖查找
- 否则应用beanFactory.resolveDependency进行扫描所有的Bean的名字收集合乎须要注入类型的Bean,而后依据多个首要的形式进行注入
@Autowire注入
应用AutowiredAnnotationBeanPostProcessor处理器拓展。
- buildAutowiringMetadata办法扫描标注了@Autowire等注解的属性或者办法
- @Autowire的元素的注入inject办法复写应用beanFactory.resolveDependency进行依赖查找,扫描所有合乎类型,进行注入。