一起来读Spring源码吧(二)容器getBean过程详解

6次阅读

共计 4184 个字符,预计需要花费 11 分钟才能阅读完成。

上一篇分析了 XmlBeanFactory 的初始化过程,此时配置的 bean 已注册到容器中,但也仅仅只是保存了 bean 的信息,并没有产生 bean 实例。下面我们以 BeanFactory.getBean(String name) 为出发点探索下 bean 的加载过程。
AbstractBeanFactory 实现了 getBean 方法,调用 doGetBean 真正开始获取 bean。首先是将参数 name 转化为 beanName,如果是“&”开头的代表是 FactoryBean(是特殊的 bean,后面会讲到)需要把“&”去除;如果是别名就去寻找它最终指向的 beanName。然后从容器的单例注册中心尝试获取 bean 实例。顺序如下:从单例缓存中(容器的 singletonObjects 属性)尝试获取;如果没有就从提早曝光单例对象(容器的 earlySingletonObjects 属性)尝试获取;如果还没有,就从 singletonFactories 中尝试获取这个 bean 的 ObjectFactory,再调用 ObjectFactory.getObject() 获取到 bean,放入 earlySingletonObjects,把 ObjectFactory 从 singletonFactories 中移除(是不是很混乱?别急,这是 Spring 为了避免循环依赖做出的策略,后面我们会解释)。如果没有获取到,也就是说要新建一个,先检查 bean 是否已经在原型创建中(避免原型的循环依赖),再在容器中查找是否存在 beanName 对应的 BeanDefinition,找不到的话就递归从父容器查找;然后如果 BeanDefinition 有依赖(也就是 bean 定义时有 depends- n 属性)就先把依赖关系注册到容器的 dependentBeanMap,再递归加载依赖的 bean;然后根据 BeanDefinition 设置的 scope 选择创建单例、原型还是其他 scope 的 bean 实例。单例的话调用 getSingleton 创建单例;原型的需要先把 beanName 注册到容器的 prototypesCurrentlyInCreation 中(为了防止循环依赖)然后调用 createBean 创建 bean 实例,随后从 prototypesCurrentlyInCreation 找中移除 beanName。创建出的实例跟前面在缓存中获取到的一样并不会直接返回,而是调用 getObjectForBeanInstance,如果不是 FactoryBean 或者想要的就是 FactoryBean 本身(name 是 & 开头)就直接返回;否则先从工厂创建 bean 缓存 factoryBeanObjectCache 中尝试获取,没有就调用 getObjectFromFactoryBean 方法创建一个 bean 实例(是单例还会存入 factoryBeanObjectCache)返回。一大堆流程看下来是不是有点晕,让我们再来简述下步骤:1、name 转化为 beanName2、尝试从缓冲中获取单例 2.1、单例缓存 singletonObjects 中查找(这个 getSingleton 只查找不创建)2.2、提早曝光单例 earlySingletonObjects 中查找 2.3、singletonFactories 中查找 ObjectFactory 并在生产 bean 放入 earlySingletonObjects 后移除 3、缓冲中获取不到,需要新建 3.1、当前容器中查找 BeanDefinition3.2、没有的话去父容器中查找 BeanDefinition3.3、递归加载设置过的依赖 bean3.4、根据 scope 创建 bean 实例 4、如果是工厂 bean,返回生产的 bean4.1、尝试从缓存 factoryBeanObjectCache 中获取 4.2、调用 BeanFactory.getObject() 生产一个 bean 实例 4.3、如果不是应用程序本身的 bean,调用后置处理器(这个后面会重点说)4.4、是单例的话存入 factoryBeanObjectCache
现在我们大致了解了向容器获取一个 bean 的主要步骤,但是我们还是不太清楚具体是怎么创建 bean 实例的,所以我们还需要继续深入:前面说到如果是单例的话,调用 getSingleton(String beanName, ObjectFactory<?> singletonFactory)(区别于 2.1 的 getSingleton),先从 singletonObjects 查找,没有的话将 beanName 放入 singletonsCurrentlyInCreation 表示该 bean 正在加载;然后用参数 singletonFactory 的函数方法 createBean(对,就是和原型一样的那个)创建一个 bean;将 beanName 从 singletonsCurrentlyInCreation 中移除;最后将新建立的 beanName 和 bean 的映射关系保存到缓存 singletonObjects 和已注册 registeredSingletons 中,移除 singletonFactories 和 earlySingletonObjects 中的记录。步骤简述如下:3.4.1、从 singletonObjects 查找 3.4.2、设置正在加载状态 3.4.3、createBean 创建 bean3.4.4、移除正在加载状态 3.4.5、保存缓存,删除中间辅助状态
我们再来看 createBean。先从 BeanDefinition 中获取 bean 的 Class,再对 override 属性(通过 lookup-method 和 replace-method 配置,后面实例化时会用到)进行标记和验证,然后给后置处理器一个机会直接返回 bean 代理,即如果容器中有注册 InstantiationAwareBeanPostProcessor 这类后置处理器的话,就分别执行它的 postProcessBeforeInstantiation 和所有后置处理器的 postProcessAfterInstantiation,如果返回不为空就直接返回代理 bean(AOP 功能基于这里判断的);最后调用 doCreateBean 实例化 bean。步骤简述如下:3.4.3.1、从 BeanDefinition 中获取 bean 的 Class 对象 3.4.3.2、对 override 属性进行标记和验证 3.4.3.3、初始化前的短路判断 3.4.3.4、实例化 bean
继续深入 doCreateBean,第一步判断如果是单例的话从 factoryBeanInstanceCache 中获取缓存的 BeanWrapper(bean 的包装类)并从中移除,如果没有则调用 createBeanInstance 创建一个 BeanWrapper;然后应用 MergedBeanDefinitionPostProcessor(AutowiredAnnotationBeanPostProcessor,Autowired);允许循环依赖的并且自身在创建中的单例,把此单例的 ObjectFactory(SmartInstantiationAwareBeanPostProcessor,AOP)注册到 singletonFactories,同时从 earlySingletonObjects 移除对应;然后调用 populateBean 对 bean 的属性进行填充,递归初始依赖的 bean;再调用 initializeBean 执行初始化方法;对于允许循环依赖的并且自身在创建中的单例做循环依赖检查;最后注册 DisposableBean。步骤简述如下:3.4.3.4.1、尝试从 factoryBeanInstanceCache 中获取缓存 BeanWrapper3.4.3.4.2、创建一个 bean 实例返回 BeanWrapper3.4.3.4.3、应用 MergedBeanDefinitionPostProcessor3.4.3.4.4、依赖处理 3.4.3.4.5、属性填充 3.4.3.4.6、执行初始化方法 3.4.3.4.7、循环依赖检查 3.4.3.4.8、注册 DisposableBean 首先我们看如何创建一个 bean 实例。先是解析出 Class,如果工厂方法不用空,即设置了 factory-method,则使用工厂方法初始化策略;否则需要根据参数锁定构造函数,如果已经解析过了在缓存中可以找到锁定,否则进行解析锁定并加入缓存;没有锁定到有参数的构造函数的话,就使用默认构造器,如果有需要覆盖或动态替换的方法(override 属性)需要使用 CGLIB 进行动态代理,否则就用反射的方式创建实例。再来看一下属性填充。在属性设置前应用 InstantiationAwareBeanPostProcessors 的 postProcessAfterInstantiation(可以控制是否继续填充),然后根据设置的自动注入方式(名称或者类型)获取属性 bean(递归 getBean)存入 PropertyValues 中,再应用 InstantiationAwareBeanPostProcessors 的 postProcessProperties 对填充前的属性进行处理(如对属性的验证),最后将所有 PropertyValues 中的属性填充到 BeanWrapper 中。属性填充完之后就是 initializeBean 方法了。首先对实现 XXAware 接口的 bean 注入相应的资源(如实现了 BeanFactoryAware 的 bean 会注入当前 BeanFactory 的实例),然后就是注册了的 BeanPostProcessor 的 postProcessBeforeInitialization,再是激活自定义的 init 方法,先后执行实现了 InitializingBean 的 afterPropertiesSet 方法和配置 init-method 方法。最后看下 DisposableBean 的注册。注册 DisposableBean 的实现,在注销时执行来源于 DestructionAwareBeanPostProcessors、实现的 DisposableBean 的 destroy 方法还有自己配置的 destroy-method 的处理。

正文完
 0