乐趣区

关于spring:浅谈Spring设计一

总概

最近始终在思考 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。
外围接口:

  1. EnvironmentCapable:提供获取 Environment 接口
  2. ListableBeanFactory/BeanFactory:提供 Bean 依赖查找。

    至于其余的接口不是咱们聚焦的外围,能够自行查看。

Spring 的容器实现

咱们以更多应用的 java 配置 web 容器相干的一个具体实现举例:AnnotationConfigWebApplicationContext

对于应用模板办法设计模式相熟的小伙伴,肯定比拟相熟这类写法,而咱们次要的办法的外围实现在 AbstractApplicationContext#refresh 办法,该办法就是容器启动的生命周期,包含如下:

  1. 筹备 Environment
  2. 获取刷新之后的 BeanFactory
  3. 筹备实例化之后的 BeanFactory
  4. BeanFactory 的后置解决拓展办法
  5. 执行 BeanFactory 的后置处理器 BeanFactoryPostProcessor。这外面其中就有是 BeanDefinition 的扫描的拓展
  6. 注册 Bean 的后置处理器 BeanPostProcessor。这外面更多是一些依赖注入的后置处理器
  7. 初始化 messageSource
  8. 初始化事件播送器,用于事件监听器
  9. onRefresh 拓展办法
  10. 注册监听器
  11. 实现 BeanFactory 的初始化。这外面有 Bean 的生命周期的治理
  12. 实现刷新

Spring 的生命外围

咱们会去除一些监听器治理和资源管理等等这些其余性能的治理,以此更加聚焦的思考 Bean 的生命周期。去除之后的外围的容器的生命周期外围为以下几点:

  1. Environment 的治理
  2. BeanDefinition 的治理
  3. Bean 的生命周期

Environment 治理

把 Environment 领进去是因为咱们在加载 BeanDefinition 的时候须要这些配置,这一块的拓展也能够联合咱们配置核心加以举例。

BeanDefinition 治理

而对于 BeanDefinition 的治理,咱们以 Java 配置进行举例。BeanDefinition 的治理接口是 BeanDefinitionRegistry,会将 BeanDefinition 存储在容器内,供前期治理 Bean 的生命周期应用。
那么进一步去理解 BeanDefinition 的治理,咱们须要理解触发条件的治理,其中这些是由 BeanFactory 的后置处理器进行拓展管制,次要是以下步骤:

  1. BeanFactory 的后置处理器 ConfigurationClassPostProcessor 的加载
  2. BeanFactory 的后置处理器 ConfigurationClassPostProcessor 的执行
  3. BeanDefinition 的扫描
  4. 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 不进行赘述,次要有以下步骤:

  1. 从单例缓存中获取,同时对 FactoryBean 进行解决
  2. 从父容器进行依赖查找
  3. 对 Bean 的 DependsOn 有优先级须要依赖的 Bean 先依赖查找
  4. 单例进行实例化前置解决的拓展执行 InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation 如果返回不为 null 的实例,则不进行往下执行
  5. 依据反射进行实例化
  6. 执行合并 BeanDefinition,执行 MergedBeanDefinitionPostProcessor#postProcessMergedBeanDefinition
  7. 如果容许循环依赖,则先存储 Bean 实例化的 Factory,用于循环依赖执行获取晚期的 Bean
  8. 填充 Bean,进行执行实例化之后的后置处理器,InstantiationAwareBeanPostProcessor#postProcessAfterInstantiation
  9. 填充 Bean,执行属性后置处理器,InstantiationAwareBeanPostProcessor#postProcessProperties
  10. 初始化 Bean,执行 Aware 前期处理器,比方 BeanNameAware、BeanClassLoaderAware、BeanFactoryAware
  11. 初始化 Bean,初始化之前的后置处理器
  12. 初始化 Bean,执行初始化办法,包含自定义
  13. 初始化 Bean,初始化之后的后置处理器
  14. 将单例进行存储缓存

依赖注入

以 @Resource 和 @Autowire 举例。而这两个解决都是以 BeanPostprocessor 进行拓展,首先须要将须要注入的信息进行扫描,应用 InjectedElement 进行存储,而后依据不同的状况进行注入。

@Resource 注入

应用 CommonAnnotationBeanPostProcessor 处理器拓展。

  1. buildResourceMetadata 办法扫描该办法外面标注 @Resource 等注解的属性或者办法
  2. @Resource 的元素的注入进行复写应用 getResource-》autowireResource 进行依赖查找
  3. 默认调用 beanFactory.resolveBeanByName 依据名字进行依赖查找
  4. 否则应用 beanFactory.resolveDependency 进行扫描所有的 Bean 的名字收集合乎须要注入类型的 Bean,而后依据多个首要的形式进行注入
@Autowire 注入

应用 AutowiredAnnotationBeanPostProcessor 处理器拓展。

  1. buildAutowiringMetadata 办法扫描标注了 @Autowire 等注解的属性或者办法
  2. @Autowire 的元素的注入 inject 办法复写应用 beanFactory.resolveDependency 进行依赖查找,扫描所有合乎类型,进行注入。
退出移动版