写点什么

《Spring Framework 系列》- IOC

用户头像
Geek_896619
关注
发布于: 2 小时前
《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


核心方法剖析


org.springframework.beans.factory.support.AbstractBeanFactory#doGetBean
① 检查容器中有无实例,有的话直接返回Object sharedInstance = getSingleton(beanName);
@ check if the bean exists in this facotryBeanFactory parentBeanFactory = getParentBeanFactory();
③ 加载beanDefinition(checkMerged)final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);checkMergedBeanDefinition(mbd, beanName, args);
④ 判断bean的类型isSingleton()isPrototype()other
⑤ 获取单例对象sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() { @Override public Object getObject() throws BeansException { try { return createBean(beanName, mbd, args); } catch (BeansException ex) { // Explicitly remove instance from singleton cache: It might have been put there // eagerly by the creation process, to allow for circular reference resolution. // Also remove any beans that received a temporary reference to the bean. destroySingleton(beanName); throw ex; } }});

⑥ create beancreateBean(beanName, mbd, args);
复制代码


分析结论:


至此,getBean 方法的源码就结束了,我们总结一下,该方法主要做了一下的事情:


  • 检查容器 bean

  • 加载 bean Definition

  • 判断 bean 类型

  • 获取单例对象(具体功能 委派给了 AbstractAutowireCapableBeanFactory#doCreateBean 实现)




下面,继续看 AbstractAutowireCapableBeanFactory#doCreateBean 的源码,这里我们猜想一下,我们通过对 getBean 方法的查看,发现 beanDefinition 已经加载进来,但是 bean 真正的加载还未开始,doCreateBean 方法是不是创建 bean 的核心方法,另外所有的生命周期实现是否又是在这个方法中实现的呢?通过源码我们来看。


org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#doCreateBean    /*** Central method of this class: creates a bean instance,* populates the bean instance, applies post-processors, etc.* @see #doCreateBean*/    1. 执行 实例化后置处理器 - InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation    且在此处提供了一个代理特性,允许调用后置处理器 BeanPostProcessor#postProcessAfterInitialization,    此时我们对该特性先不做扩展和探讨,继续深入createBean方法// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
/** * Apply before-instantiation post-processors, resolving whether there is a * before-instantiation shortcut for the specified bean. * @param beanName the name of the bean * @param mbd the bean definition for the bean * @return the shortcut-determined bean instance, or {@code null} if none */protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) { Object bean = null; if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) { // Make sure bean class is actually resolved at this point. if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) { Class<?> targetType = determineTargetType(beanName, mbd); if (targetType != null) { bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName); if (bean != null) { bean = applyBeanPostProcessorsAfterInitialization(bean, beanName); } } } mbd.beforeInstantiationResolved = (bean != null); } return bean;}
2. 调用 AbstractAutowireCapableBeanFactory#doCreateBeanObject beanInstance = doCreateBean(beanName, mbdToUse, args);
3. 进入 创建 bean wrapper 实例方法 createBeanInstance() instanceWrapper = createBeanInstance(beanName, mbd, args);
4. 进入 实例化bean方法 instantiateBean() instantiateBean(beanName, mbd);
5. 执行构造器后置处理器 - SmartInstantiationAwareBeanPostProcessor#determineCandidateConstructors tips: 用于构造器注册(涉及 spring 3种依赖注入的方式中的构造器注入方式)Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);if (ctors != null || mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR || mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) { return autowireConstructor(beanName, mbd, ctors, args);}
/** * "autowire constructor" (with constructor arguments by type) behavior. * Also applied if explicit constructor argument values are specified, * matching all remaining arguments with beans from the bean factory. * <p>This corresponds to constructor injection: In this mode, a Spring * bean factory is able to host components that expect constructor-based * dependency resolution. * @param beanName the name of the bean * @param mbd the bean definition for the bean * @param ctors the chosen candidate constructors * @param explicitArgs argument values passed in programmatically via the getBean method, * or {@code null} if none (-> use constructor argument values from bean definition) * @return BeanWrapper for the new instance */ protected BeanWrapper autowireConstructor( String beanName, RootBeanDefinition mbd, Constructor<?>[] ctors, Object[] explicitArgs) {
6. 执行 合并bean信息后置处理器 -(MergedBeanDefinitionPostProcessor#postProcessMergedBeanDefinition) applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName); 7. 实例化完成,进入填充属性方法 populateBean() populateBean(beanName, mbd, instanceWrapper); 8. 执行 实例化后置处理器 - InstantiationAwareBeanPostProcessor#postProcessAfterInstantiation if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) { 9. 依赖注入处理 -- 但未真正注入bean中,放入 MutablePropertyValues(newPvs) 变量中 autowireByName(beanName, mbd, bw, newPvs); autowireByType(beanName, mbd, bw, newPvs);
10. 执行 实例化后置处理器 - InstantiationAwareBeanPostProcessor#postProcessPropertyValues tips:此阶段可以对bean属性进行二次加工,因为此时 属性还未真正注入进 成品bean 中 pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName); 11. bean 的属性赋值 重点方法(暂不做讨论) applyPropertyValues(beanName, mbd, bw, pvs); 12.执行 初始化后置处理器 - BeanPostProcessor#postProcessBeforeInstantiation wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName); 12.bean 级别(bean视角)的生命周期函数执行 exposedObject = initializeBean(beanName, exposedObject, mbd); invokeAwareMethods(beanName, bean); --> 调用 Aware类型的Method private void invokeAwareMethods(final String beanName, final Object bean) { if (bean instanceof Aware) { if (bean instanceof BeanNameAware) { ((BeanNameAware) bean).setBeanName(beanName); } if (bean instanceof BeanClassLoaderAware) { ((BeanClassLoaderAware) bean).setBeanClassLoader(getBeanClassLoader()); } if (bean instanceof BeanFactoryAware) { ((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this); } } } invokeInitMethods(beanName, wrappedBean, mbd); --> 调用 InitializingBean#afterPropertiesSet --> 调用 bean xml 的 Init-Method
13.执行 初始化后置处理器 - BeanPostProcessor#postProcessAfterInstantiation wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
复制代码


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


未完待续。。。

用户头像

Geek_896619

关注

还未添加个人签名 2018.11.08 加入

还未添加个人简介

评论

发布
暂无评论
《Spring Framework 系列》- IOC