《Spring Framework 系列》- IOC
议题概览
IOC 的底层实现原理
生命周期钩子方法实现
bean 的反射实例化实现
IOC 的生命周期概览
容器角度
bean 角度
IOC 扩展点探究
生命周期钩子函数运用
AOP
bean 代理
属性编辑
自我思考
一。我认为的 spring framework 是什么?
首先,我认为 spring framework 是一个 基于 Java 的企业开发框架,它提供了大量的基础设施组件支持,如 依赖管理,web,dao,事件,aop 等。其次,我认为 spring 还是 灵活扩展的框架,它提供了非常精细化的生命周期管理,每个生成周期的阶段都预留了不同的接口和钩子,供我们做一些定制化的实现。另外,我认为 spring framework 还在不断得更迭,再往 cloud 方向发展,从 springframwork,再到 boot,再到 cloud,再到为来的 cloud native(graal vm),spring 对自己的定位还在不断的变化。目前来看,spring framework 已经是 Java 领域的开发框架事实标准。
二。为什么 spring framework 要提供如此多,如此精细的生命周期管理?
可以分为两方面回答这个问题,一个是官方的角度,还有一个是我自己的角度。
先是官方的角度。在 spring framework 的官方文档中,提到了 spring 的设计哲学,我认为有两点和此有关,原文如下。
Provide choice at every level. Spring lets you defer design decisions as late as possible. For example, you can switch persistence providers through configuration without changing your code. The same is true for many other infrastructure concerns and integration with third-party APIs.
Accommodate diverse perspectives. Spring embraces flexibility and is not opinionated about how things should be done. It supports a wide range of application needs with different perspectives.
第一点的意思是 spring 让开发人员 有尽可能多的选择,允许他们可以在尽可能晚的阶段通过 spring 的生命周期管理自己的程序。第二点是 spring 在设计阶段是灵活的,具有包容性的。它支持在不同的程序周期视角做一些处理。
其次是我的观点。
议题探究
深入 spring 生命周期管理
BeanFactory 中 bean 生命周期管理
核心组件
核心工厂组件
BeanFactory
容器组件
BeanPostProcessor
bean instance 相关
如果考虑在 bean 实例方面做文章,可以考虑实现 BeanPostProcessor
InstantiationAwareBeanPostProcessor(核心类)-- 重点分析(bean 在每个阶段做的事情?属性编辑)
实例化前后容器介入
属性编辑阶段
初始化前后容器介入
DestructionAwareBeanPostProcessor
BeanFactoryPostProcessor -- 属于 Application Context,不是 beanfactory 使用
BeanDefinition 相关
application context can detect the BeanFactoryPostProcessor bean,and load them before other beans be created
bean 定义前 的 前置操作
PropertyResourceConfigurer(属性编辑?)
bean 组件
Aware
BeanNameAware -- 此阶段 bean 已经基本成型
BeanClassLoaderAware
BeanFactoryAware
InitializingBean
DisposableBean // destory
核心组件探究
BeanPostProcessor
bean 实例化及依赖注入完成阶段
org.springframework.beans.factory.config.BeanPostProcessor#postProcessBeforeInitialization
此过程,bean 的属性和依赖已经填充(populate)完毕
see : before - org.springframework.beans.factory.InitializingBean#afterPropertiesSet
org.springframework.beans.factory.config.BeanPostProcessor#postProcessAfterInitialization
FactoryBean,proxy,wrapper 相关
see: after - org.springframework.beans.factory.InitializingBean#afterPropertiesSet
see: after - init-method
InstantiationAwareBeanPostProcessor
bean 实例化及属性填充阶段
在精确属性被设置 和 依赖注入阶段之前
目标与作用
创建目标代理:create proxies with special TargetSources (pooling targets,lazily initializing targets, etc)
额外注入:implement additional injection strategies such as field injection.
注意事项:
这个接口一般是 spring internal 使用
建议实现 BeanPostProcessor 或者 derive InstantiationAwareBeanPostProcessorAdapter
org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation
before Instantiation
org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor#postProcessAfterInstantiation
after Instantiation ,before populate properties
tips : ideal callback for performing custom field injection on the given bean instance
org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor#postProcessPropertyValues(重点方法)
属性装配预处理
从两个角度剖析 bean 的生命周期
tips: 我认为 spring 对 bean 的阶段处理分为 容器级 和 bean 级 是如下原因:
容器级是对整体的容器内对象做统一的处理,是广义性的
bean 级是对单位 bean 做阶段的细化处理,是狭义的
容器阶段 和 bean 定义阶段 的 协作处理,构造出了 灵活可扩展的 bean 生命周期
BeanFactory Bean 定义加载流程图
源码分析
在看源码之前,提出问题:
① 如上的这些 bean 生命周期是如何嵌入到 create bean 的周期中的?
② 代码的层次性是怎样的,spring contexts 都有非常多的 层次性(Herdex),这样设计的目的又是什么?
BeanFactory 加载 Bean 步骤
org.springframework.beans.factory.support.DefaultListableBeanFactory#getBean(java.lang.Class<T>)
org.springframework.beans.factory.support.DefaultListableBeanFactory#resolveNamedBean(java.lang.Class<T>, java.lang.Object...)
org.springframework.beans.factory.support.AbstractBeanFactory#doGetBean // 核心方法,重点看
org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#getSingleton(java.lang.String, org.springframework.beans.factory.ObjectFactory<?>)
org.springframework.beans.factory.support.AbstractBeanFactory#createBean // 核心类(central class):create bean instance;populate properties;apply post-processor
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#doCreateBean
核心方法剖析
分析结论:
至此,getBean 方法的源码就结束了,我们总结一下,该方法主要做了一下的事情:
检查容器 bean
加载 bean Definition
判断 bean 类型
获取单例对象(具体功能 委派给了 AbstractAutowireCapableBeanFactory#doCreateBean 实现)
下面,继续看 AbstractAutowireCapableBeanFactory#doCreateBean 的源码,这里我们猜想一下,我们通过对 getBean 方法的查看,发现 beanDefinition 已经加载进来,但是 bean 真正的加载还未开始,doCreateBean 方法是不是创建 bean 的核心方法,另外所有的生命周期实现是否又是在这个方法中实现的呢?通过源码我们来看。
BeanFactory 加载 Bean 调用时序图
TODO : 待完善。。。
源码分析总结:
或许上面的分析过程看起来有点晕,后续会补充时序图类型的流程过程调用,以此来更容易理解。
通过对 doCreateBean 方法的源码分析,我们发现,对 bean 的实例化,属性注入 以及 初始化的过程都在 此方法中,这个方法是名副其实的 spring ioc 核心方法~
这个方法做了一下几件事情:
bean 的实例化(包装类型)
属性注入
bean 的初始化
以上几个过程的所有生命周期钩子
我们尝试回答一下上面我们提的几个问题:
① 如上的这些 bean 生命周期钩子是如何嵌入到 create bean 的周期中的?
答:spring 的生命周期钩子 是在容器初始化 bean 的加载时(实例化,属性编辑,初始化过程)通过回调的方式增加的一些钩子调用点,
其核心方法时 AbstractBeanFactory#createBean/AbstractAutowiredCapableBeanFactory#doCreateBean
典型的比如几个后置处理器:
InstantiationAwareBeanPostProcessor
BeanPostProcessor
MergedBeanDefinitionPostProcessor
SmartInstantiationAwareBeanPostProcessor
典型的 bean 级别接口:
BeanNameAware
BeanClassLoaderAware
BeanFactoryAware
InitializingBean
bean xml 定义
这些生命周期可以介入到 bean 创建的不同阶段,spring 通过这样的方式完成 bean 的生命周期过程。
TIPS:
spring framework 博大精深,仅仅是在 BeanFactory 中的 bean 定义及实例化就如此复杂,入口和定制点如此多,况且我们还没有仔细得分析每个暴露的接口都可以做什么样的功能,如果我们想做 bean 代理层,是通过哪些生命周期过程可以嵌入?然后如果我们想实现 AOP 功能,对 bean 做动态的代理,我们又可以在哪些过程参与注入,都可以在后续的章节中探讨,在此,我们先保持疑问和期待~
类的层次结构
BeanFactory
未完待续。。。
评论