怎么看网站开发语言信息,宁波网站推广软件服务,网站运营每天做的,做墙报的网站目录 前言阅读准备阅读指引阅读建议 课程内容一、SpringIOC之实例化1.1 简单回顾1.2 概念回顾1.3 核心方法讲解 二、方法讲解2.1 AbstractBeanFactory#getMergedLocalBeanDefinition#xff1a;合并BeanDefinition2.2 AbstractAutowireCapableBeanFactory#createBean#xff… 目录 前言阅读准备阅读指引阅读建议 课程内容一、SpringIOC之实例化1.1 简单回顾1.2 概念回顾1.3 核心方法讲解 二、方法讲解2.1 AbstractBeanFactory#getMergedLocalBeanDefinition合并BeanDefinition2.2 AbstractAutowireCapableBeanFactory#createBean创建Bean2.3 AbstractAutowireCapableBeanFactory#resolveBeanClass加载类*2.4 AbstractAutowireCapableBeanFactory#resolveBeforeInstantiation【实例化前】入口2.5 AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsBeforeInstantiation【实例化前】真正干活的地方2.6 AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsAfterInitialization第一次可能调用【初始化后】2.7 AbstractAutowireCapableBeanFactory#doCreateBean【实例化】入口包括后续的实例化过程*2.8 AbstractAutowireCapableBeanFactory#createBeanInstance实例化2.8.1 Supplier创建对象2.8.2 工厂方法创建对象2.8.3 构造方法创建对象 2.9 AbstractAutowireCapableBeanFactory#autowireConstructor推断构造方法2.10 AbstractAutowireCapableBeanFactory#applyMergedBeanDefinitionPostProcessorsBeanDefinition后置处理2.11 AbstractAutowireCapableBeanFactory#populateBean属性注入包含实例化后方法总结后 三、实例化逻辑流程图 学习总结 前言
阅读准备
由于Spring源码分析是一个前后联系比较强的过程而且这边分析也是按照代码顺序讲解的所以不了解前置知识的情况下大概率没办法看懂当前的内容。所以特别推荐看看我前面的文章自上而下次序
Spring底层核心原理解析【学习难度★★☆☆☆】手写简易Spring容器过程分析【学习难度★★☆☆☆】Spring之底层架构核心概念解析【学习难度★★★☆☆重要程度★★★★★】Bean的生命周期流程图【学习难度☆☆☆☆☆重要程度★★★★★】Spring之Bean的生命周期源码解析——阶段一扫描生成BeanDefinition【学习难度★★☆☆☆重要程度★★★☆☆】
PS特别是《Bean的生命周期流程图》帮大家【开天眼】先了解下流程。毕竟【通过业务了解代码远比通过代码了解业务简单的多】 PS特别是《Bean的生命周期流程图》帮大家【开天眼】先了解下流程。毕竟【通过业务了解代码远比通过代码了解业务简单的多】 PS特别是《Bean的生命周期流程图》帮大家【开天眼】先了解下流程。毕竟【通过业务了解代码远比通过代码了解业务简单的多】
阅读指引
我们在上一节课已经说到过了本次Spring源码剖析的总入口是new AnnotationConfigApplicationContext(org.tuling.spring);这里就不再重复解释了。本节课要说的内容是SpringIOC的实例化我们这里直接给到入口吧调用链如下调用链比较深不要纠结细枝末节
AbstractApplicationContext#refresh刷新方法不用在意AbstractApplicationContext#finishBeanFactoryInitialization在这里实例化所有剩余的(非lazy-init)单例DefaultListableBeanFactory#preInstantiateSingletons在这里实例化所有剩余的(非lazy-init)单例上面的方法核心干活的方法就是这里DefaultListableBeanFactory#getBean获取Bean的方法AbstractBeanFactory#doGetBean返回指定bean的一个实例它可以是共享的也可以是独立的上面这个AbstractBeanFactory#doGetBean里面的一段局部代码写的回调方法如下 // 如果是单例创建bean实例if (mbd.isSingleton()) {sharedInstance getSingleton(beanName, () - {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;}});beanInstance getObjectForBeanInstance(sharedInstance, name, beanName, mbd);}AbstractAutowireCapableBeanFactory#createBean这个类的中心方法创建一个bean实例填充bean实例应用后处理器等等。
如上面的调用链所示最后一个方法才是我们本次要研究的核心方法。而且通过注释我想大家也看到了这个方法不单单干了实例化的工作还有属性填充、各种后置处理器等。PS哈哈同学们我知道这个【实例化】调用链挺深的但是大家不要烦恼只要切记【不要纠结那些细枝末节】那一切都OK我们老老实实地跟着主线来研究就好毕竟这些才是核心
阅读建议
看源码切记纠结细枝末节不然很容易陷进去。正常来说看主要流程就好了遇到不懂的多看看类注释或者方法注释。Spring这种优秀源码注释真的非常到位如果你是idea用户多用F11的书签功能。 Ctrl F11 选中文件 / 文件夹使用助记符设定 / 取消书签 必备Shift F11 弹出书签显示层 必备Ctrl 1,2,3…9 定位到对应数值的书签位置 必备
课程内容
一、SpringIOC之实例化
这里说的【实例化】是指单例的实例化原型prototype不包含在内
1.1 简单回顾
大家知道实例化的过程是怎样的吗哈我知道大部分的同学可能都不会知道。所以呢我希望大家真的要有去看过《 Bean的声明周期流程图》因为通过【代码去理解业务】远远比【通过业务理解代码】难得多直接看个图吧起码咱得知道【实例化到底干了什么有哪些步骤】我们才能更好的去研究。 如上图所示实例化包含了合并BeanDefinition、加载类、实例化之前、推断构造方法、实例化、BeanDefinition的后置处理、实例化后等这些关键步骤。这就是我们本篇文章研究的核心
1.2 概念回顾
在这个【实例化】过程中涉及到了一些Spring底层设计的概念我在上一个笔记里面有大概介绍过Spring底层概念的一些讲解不记得的同学记得回去翻一翻。 主要涉及的概念有
BeanDefinition设计图纸BeanDefinition表示Bean定义BeanDefinition中存在很多属性用来描述一个Bean的特征BeanPostProcessorSpring重要的拓展点Bean的后置处理器对Bean做拓展操作。我们前面说过BeanPostProcessor提供了【初始化前/后】两个拓展方法。但是这里Spring内部对这个接口做了很多拓展新增了一些继承自BeanPostProcessor的子类或者子接口。在实例化阶段主要用到的接口如下 InstantiationAwareBeanPostProcessor直译过来就是能感知实例化的Bean后置处理器。而这个继承自BeanPostProcessor显然也具备这【初始化前/后】两个拓展方法。另外通过InstantiationAwareBeanPostProcessor的名字大家也能猜到了它肯定是具有对【实例化】阶段拓展的能力的。接口定义在后面。SmartInstantiationAwareBeanPostProcessor直译过来就是智能的能感知实例化的Bean后置处理器。在这个接口中拓展了InstantiationAwareBeanPostProcessor接口新增了几个函数其中就包括了推断构造的实现。另外这是一个框架内部使用接口。接口定义在后面。MergedBeanDefinitionPostProcessor直译过来就是合并BeanDefinition的后置处理器。运行时用于合并bean定义的后处理器回调接口。接口定义在后面。
InstantiationAwareBeanPostProcessor接口定义如下
/*** BeanPostProcessor的子接口用于添加实例化前回调以及实例化后但显式属性设置或自动生成之前的回调。* 通常用于抑制特定目标bean的默认实例化例如创建具有特殊TargetSources的代理(池化目标、惰性初始化目标等)或者实现额外的注入策略如字段注入。* 注:此接口为专用接口主要供框架内部使用。建议尽可能实现普通的BeanPostProcessor接口。* 自:* 1.2* 参见:* org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.setCustomTargetSourceCreators, org.springframework.aop.framework.autoproxy.target.LazyInitTargetSourceCreator* 作者:* 于尔根·霍勒罗德·约翰逊*/
public interface InstantiationAwareBeanPostProcessor extends BeanPostProcessor {/*** 在目标bean实例化之前应用这个BeanPostProcessor。返回的bean对象可能是要使用的代理而不是目标bean从而有效地抑制目标bean的默认实例化。* 如果此方法返回一个非空对象则bean创建过程将会中断。应用的唯一进一步处理是来自配置的BeanPostProcessors的postProcessAfterInitialization回调。* 这个回调将应用于带有bean类的bean定义以及工厂方法定义在这种情况下返回的bean类型将在这里传递。* 后置处理器可以实现扩展的SmartInstantiationAwareBeanPostProcessor接口以便预测它们将在这里返回的bean对象的类型。* 默认实现返回null。* 参数:* beanClass——要实例化的bean的类* beanName—bean的名称* 返回:* 要公开的bean对象而不是目标bean的默认实例或者为空继续进行默认实例化* 抛出:* BeansException -在错误的情况下* 参见:* postProcessAfterInstantiation, org.springframework.beans.factory.support.AbstractBeanDefinition.getBeanClass() org.springframework.beans.factory.support.AbstractBeanDefinition.getFactoryMethodName()*/Nullabledefault Object postProcessBeforeInstantiation(Class? beanClass, String beanName) throws BeansException {return null;}/*** 在bean通过构造函数或工厂方法实例化之后但在Spring属性填充(来自显式属性或自动装配)发生之前执行操作。* 这是在Spring自动装配开始之前对给定bean实例执行自定义字段注入的理想回调。* 默认实现返回true。* 参数:* Bean—已创建的Bean实例其属性尚未设置* beanName—bean的名称* 返回:* 如果应该在bean上设置属性则为True;如果应该跳过属性人口则为False。正常的实现应该返回true。返回false还将阻止在此bean实例上调用任何后续的InstantiationAwareBeanPostProcessor实例。* 抛出:* BeansException -在错误的情况下* 参见:* postProcessBeforeInstantiation*/default boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {return true;}/*** 在工厂将给定的属性值应用到给定的bean之前对它们进行后处理不需要任何属性描述符。* 如果实现提供自定义postProcessPropertyValues实现则应该返回null(默认值)否则则返回pvs。在该接口的未来版本中(删除了postProcessPropertyValues)默认实现将直接返回给定的pv。* 参数:* PVS—工厂将要应用的属性值(永远不会为空)* bean——已创建的bean实例但其属性尚未设置* beanName—bean的名称* 返回:* 应用于给定bean的实际属性值(可以是传入的PropertyValues实例)或者null它继续处理现有属性但特别地继续调用postProcessPropertyValues(需要为当前bean类初始化PropertyDescriptors)。* 抛出:* BeansException -在错误的情况下* 自:* 5.1* 参见:* postProcessPropertyValues*/Nullabledefault PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName)throws BeansException {return null;}/*** 在工厂将给定属性值应用到给定bean之前对它们进行后处理。允许检查是否满足所有依赖项例如基于bean属性设置器上的“Required”注释。* 还允许替换要应用的属性值通常通过基于原始PropertyValues创建新的MutablePropertyValues实例添加或删除特定值。* 默认实现按原样返回给定的pv。* 弃用* 从5.1开始支持postProcessProperties(PropertyValues, Object, String)* 参数:* PVS—工厂将要应用的属性值(永远不会为空)* PDS——目标bean的相关属性描述符(忽略了依赖类型——工厂专门处理的依赖类型——已经过滤掉了)* bean——已创建的bean实例但其属性尚未设置* beanName—bean的名称* 返回:* 应用于给定bean的实际属性值(可以是传入的PropertyValues实例)或者为null以跳过属性填充* 抛出:* BeansException -在错误的情况下* 参见:* postProcessProperties, org.springframework.beans.MutablePropertyValues*/DeprecatedNullabledefault PropertyValues postProcessPropertyValues(PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException {return pvs;}
}SmartInstantiationAwareBeanPostProcessor接口定义如下
/*** 扩展了InstantiationAwareBeanPostProcessor接口添加了一个回调函数用于预测被处理bean的最终类型。* 注:此接口为专用接口主要供框架内部使用。一般来说应用程序提供的后处理器应该简单地实现普通的BeanPostProcessor接口或者从InstantiationAwareBeanPostProcessorAdapter类派生。即使在点发布版本中也可能向该接口添加新方法。* 自:* 2.0.3* 参见:* InstantiationAwareBeanPostProcessorAdapter* 作者:* Juergen hoel*/
public interface SmartInstantiationAwareBeanPostProcessor extends InstantiationAwareBeanPostProcessor {/*** 预测这个处理器的postProcessBeforeInstantiation回调最终返回的bean的类型。* 默认实现返回null。* 参数:* beanClass—bean的原始类beanName—bean的名称* 返回:* bean的类型如果不可预测则为空* 抛出:* BeansException -在错误的情况下*/Nullabledefault Class? predictBeanType(Class? beanClass, String beanName) throws BeansException {return null;}/*** 确定要为给定bean使用的候选构造函数。* 默认实现返回null。* 参数:* beanClass—bean的原始类(不为空)beanName—bean的名称* 返回:* 候选构造函数如果未指定则为空* 抛出:* BeansException -在错误的情况下*/Nullabledefault Constructor?[] determineCandidateConstructors(Class? beanClass, String beanName)throws BeansException {return null;}/*** 获取对指定bean的早期访问的引用通常是为了解析循环引用。* 这个回调让后处理器有机会尽早公开包装器——也就是说在目标bean实例完全初始化之前。暴露的对象应该等同于postProcessBeforeInitialization / postProcessAfterInitialization所暴露的对象。请注意此方法返回的对象将用作bean引用除非后处理器返回与所述后处理回调不同的包装器。换句话说:那些处理后回调可能最终公开相同的引用或者返回那些后续回调的原始bean实例(如果受影响的bean的包装器已经为对该方法的调用构建了那么默认情况下它将作为最终bean引用公开)。* 默认实现按原样返回给定的bean。* 参数:* bean—原始bean实例beanName—bean的名称* 返回:* 要作为bean引用公开的对象(通常将传入的bean实例作为默认值)* 抛出:* BeansException -在错误的情况下*/default Object getEarlyBeanReference(Object bean, String beanName) throws BeansException {return bean;}
}MergedBeanDefinitionPostProcessor接口定义如下
/*** 运行时用于合并bean定义的后处理器回调接口。BeanPostProcessor实现可以实现这个子接口以便对合并的bean定义(原始bean定义的处理副本)进行后处理Spring BeanFactory使用合并的bean定义来创建bean实例。* 例如postProcessMergedBeanDefinition方法可以对bean定义进行内省以便在对bean的实际实例进行后处理之前准备一些缓存的元数据。也允许修改bean定义但只允许修改用于并发修改的定义属性。本质上这只适用于在RootBeanDefinition本身上定义的操作而不适用于其基类的属性。* 自:* 2.5* 参见:* org.springframework.beans.factory.config.ConfigurableBeanFactory.getMergedBeanDefinition* 作者:* Juergen hoel*/
public interface MergedBeanDefinitionPostProcessor extends BeanPostProcessor {/*** 对指定bean的给定合并bean定义进行后处理。* 参数:* beanDefinition—为bean合并的bean定义beanType—托管bean实例的实际类型beanName—bean的名称* 参见:* AbstractAutowireCapableBeanFactory.applyMergedBeanDefinitionPostProcessors*/void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class? beanType, String beanName);/*** 通知指定名称的bean定义已被重置并且此后处理器应清除受影响bean的所有元数据。* 默认实现为空。* 参数:* beanName—bean的名称* 自:* 5.1* 参见:* DefaultListableBeanFactory.resetBeanDefinition*/default void resetBeanDefinition(String beanName) {}
}这里还是有一点想要提醒各位的BeanPostProcessor是被Spring定义为【钩子】的而钩子很多时候都是为了改变系统原有行为的。这种改变通常体现在对Bean生命周期的影响或者某个生命周期完成对象的改变等等。这么说有点晦涩难懂通俗点讲就是Bean可能不会经过完整生命周期比如【实例化前】之后直接就跳到【初始化后】了没有经过原本定义的【实例化】、【实例化后】、【其他后置处理】等或者原本初始化动作是Spring帮我门完成的但是由于我们自己介入了Spring就不帮我们初始化了而是按照程序员意愿
文章链接 《【Spring专题】Spring之底层架构核心概念解析》
1.3 核心方法讲解
整个IOC实例化的主干过程主要涉及了【2个类11个核心方法】。下面我们将会按照调用次序依次讲解各个方法。
二、方法讲解
我们在上面说到过这里的实例化过程包含了合并BeanDefinition、加载类、实例化之前、推断构造方法、实例化、BeanDefinition的后置处理、实例化后等关键步骤。所以在整个调用链上基本上就是干了这些事情。 我们前面说过本次的实例化代码入口如下 // 如果是单例创建bean实例if (mbd.isSingleton()) {sharedInstance getSingleton(beanName, () - {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;}});beanInstance getObjectForBeanInstance(sharedInstance, name, beanName, mbd);}2.1 AbstractBeanFactory#getMergedLocalBeanDefinition合并BeanDefinition 方法调用链AbstractBeanFactory#doGetBean里面调用的 全路径org.springframework.beans.factory.support.AbstractBeanFactory#getMergedLocalBeanDefinition 方法注释返回合并的RootBeanDefinition如果指定的bean对应于子bean定义则遍历父bean定义。 我们在上节课最后的地方提到过这个这边就不重复讲了但是他是算在实例化过程里面的嘻嘻
2.2 AbstractAutowireCapableBeanFactory#createBean创建Bean 方法调用链AbstractBeanFactory#doGetBean里面调用的 全路径org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#createBean 方法注释这个类的中心方法:创建一个bean实例填充bean实例应用后处理器等等。 源码如下 Overrideprotected Object createBean(String beanName, RootBeanDefinition mbd, Nullable Object[] args)throws BeanCreationException {if (logger.isTraceEnabled()) {logger.trace(Creating instance of bean beanName );}RootBeanDefinition mbdToUse mbd;// 步骤一加载类Class? resolvedClass resolveBeanClass(mbd, beanName);if (resolvedClass ! null !mbd.hasBeanClass() mbd.getBeanClassName() ! null) {mbdToUse new RootBeanDefinition(mbd);mbdToUse.setBeanClass(resolvedClass);}// 不用管这个try {mbdToUse.prepareMethodOverrides();}catch (BeanDefinitionValidationException ex) {throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),beanName, Validation of method overrides failed, ex);}try {// 步骤二实例化前Object bean resolveBeforeInstantiation(beanName, mbdToUse);if (bean ! null) {return bean;}}catch (Throwable ex) {throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,BeanPostProcessor before instantiation of bean failed, ex);}try {// 步骤三创建BeanObject beanInstance doCreateBean(beanName, mbdToUse, args);if (logger.isTraceEnabled()) {logger.trace(Finished creating instance of bean beanName );}return beanInstance;}catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {// A previously detected exception with proper bean creation context already,// or illegal singleton state to be communicated up to DefaultSingletonBeanRegistry.throw ex;}catch (Throwable ex) {throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName, Unexpected exception during bean creation, ex);}}方法解读上面代码老长一段trt-catch占了一半啊哈哈。 这里面的步骤就三个下面也会讲到。
resolveBeanClass加载类resolveBeforeInstantiation实例化前doCreateBean真正创建Bean的地方
2.3 AbstractAutowireCapableBeanFactory#resolveBeanClass加载类
PS不算很重要知道有这个步骤就好 方法调用链由2.2的createBean调用过来 全路径org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#resolveBeanClass 方法注释这个类的中心方法:创建一个bean实例填充bean实例应用后处理器等等。 源码如下
protected Class? resolveBeanClass(RootBeanDefinition mbd, String beanName, Class?... typesToMatch)throws CannotLoadBeanClassException {if (mbd.hasBeanClass()) {return mbd.getBeanClass();}if (System.getSecurityManager() ! null) {return AccessController.doPrivileged((PrivilegedExceptionActionClass?)() - doResolveBeanClass(mbd, typesToMatch), getAccessControlContext());}else {return doResolveBeanClass(mbd, typesToMatch);}
}方法解读这个代码外层挺简单的也许大家对比System.getSecurityManager() ! null这个比较难理解而已。这是Spring内部的一个安全管理器很多时候都是不开启的。后面也会出现大量这种代码反正遇到这个就直接看else的逻辑就好了。至于里层的doResolveBeanClass源码如下 private Class? doResolveBeanClass(RootBeanDefinition mbd, Class?... typesToMatch)throws ClassNotFoundException {// 步骤一获取默认的类加载器ClassLoader beanClassLoader getBeanClassLoader();ClassLoader dynamicLoader beanClassLoader;boolean freshResolve false;// 步骤二在我们这个调用链上不会走这里因为typesToMatch为nullif (!ObjectUtils.isEmpty(typesToMatch)) {ClassLoader tempClassLoader getTempClassLoader();if (tempClassLoader ! null) {dynamicLoader tempClassLoader;freshResolve true;if (tempClassLoader instanceof DecoratingClassLoader) {DecoratingClassLoader dcl (DecoratingClassLoader) tempClassLoader;for (Class? typeToMatch : typesToMatch) {dcl.excludeClass(typeToMatch.getName());}}}}// 步骤三String className mbd.getBeanClassName();if (className ! null) {// 步骤3.1这里也不用怎么看这是Spring表达式解析的东西。Spring表达式这个东西我们用的很少类似EL表达式这样来理解Object evaluated evaluateBeanDefinitionString(className, mbd);if (!className.equals(evaluated)) {if (evaluated instanceof Class) {return (Class?) evaluated;}else if (evaluated instanceof String) {className (String) evaluated;freshResolve true;}else {throw new IllegalStateException(Invalid class name expression result: evaluated);}}if (freshResolve) {if (dynamicLoader ! null) {try {// 步骤3.2 加载类return dynamicLoader.loadClass(className);}catch (ClassNotFoundException ex) {if (logger.isTraceEnabled()) {logger.trace(Could not load class [ className ] from dynamicLoader : ex);}}}return ClassUtils.forName(className, dynamicLoader);}}// 步骤四正常来说走的是这里。使用默认的类加载器加载类return mbd.resolveBeanClass(beanClassLoader);}方法解读在这里大体分为4个步骤。步骤一就是获取类加载器往里追踪会发现实际上调用的是ClassUtils.getDefaultClassLoader()方法。里面的代码挺简单的获取原则如下需要一点JVM底子才懂不了解也无所谓
优先返回当前线程中的ClassLoader线程中类加载器为null的情况下返回ClassUtils类的类加载器如果ClassUtils类的类加载器为空那么则表示是Bootstrap类加载器加载的ClassUtils类那么则返回系统类加载器
步骤二就是第一个if在我们这里的调用链上是不会进来这里的因为typeToMatch是null 步骤三可看可不看一般也不会进来这里。这是Spring表达式解析的东西。Spring表达式这个东西我估计大部分人都没用过吧…类似EL表达式这样来理解 步骤四正常来说会执行到这里然后在这里进行类加载并且通过反射获得class对象代码如下所示 public Class? resolveBeanClass(Nullable ClassLoader classLoader) throws ClassNotFoundException {String className getBeanClassName();if (className null) {return null;}Class? resolvedClass ClassUtils.forName(className, classLoader);this.beanClass resolvedClass;return resolvedClass;}*2.4 AbstractAutowireCapableBeanFactory#resolveBeforeInstantiation【实例化前】入口
PS终于来到这里了这才是核心考点 方法调用链由2.2的createBean调用过来 全路径org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#resolveBeforeInstantiation 方法注释应用实例化前的后处理器解析指定bean是否存在实例化前的快捷方式。 源码如下 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;}
方法解读代码短短的几行。首先通过hasInstantiationAwareBeanPostProcessors看看是否有InstantiationAwareBeanPostProcessors。有则调用对应的【实例化前】方法即applyBeanPostProcessorsBeforeInstantiation这里才是真正干活的地方后面介绍。
这里有一个细节那就是applyBeanPostProcessorsBeforeInstantiation如果返回的对象不为空则直接调用applyBeanPostProcessorsAfterInitialization走bean的【初始化后】方法了。这说明Bean的生命周期被改变而且如果这里的Bean有值的话外层直接返回创建成功了不会继续往下走了如下所示2.2的createBean调用处代码
Object bean resolveBeforeInstantiation(beanName, mbdToUse);
if (bean ! null) {return bean;
}2.5 AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsBeforeInstantiation【实例化前】真正干活的地方 方法调用链由2.4的resolveBeforeInstantiation调用过来 全路径org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsBeforeInstantiation 方法注释将InstantiationAwareBeanPostProcessors应用到指定的bean定义(通过类和名称)调用它们的postProcessBeforeInstantiation方法。如果返回不为空则无需Spring帮我们实例化了 源码如下 Nullableprotected Object applyBeanPostProcessorsBeforeInstantiation(Class? beanClass, String beanName) {for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {Object result bp.postProcessBeforeInstantiation(beanClass, beanName);if (result ! null) {return result;}}return null;}方法解读这里终于出现我们之前说的核心InstantiationAwareBeanPostProcessor了。老样子遍历所有的InstantiationAwareBeanPostProcessor然后调用postProcessBeforeInstantiation()。这里只要找到一个InstantiationAwareBeanPostProcessor的postProcessBeforeInstantiation()返回不为空则直接停止遍历。 这个方法其实隐含的意思是在Spring帮我们实例化之前Spring会先去找找看用户有没有对当前beanName对应的class有自己的实例化想法如果有则Spring就不帮我们创建了。
2.6 AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsAfterInitialization第一次可能调用【初始化后】 方法调用链由2.4的resolveBeforeInstantiation调用过来 全路径org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsAfterInitialization 方法注释应用初始化后方法。通常调用此方法的时候会认为已经经过了属性填充、初始化等 源码如下 public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)throws BeansException {Object result existingBean;for (BeanPostProcessor processor : getBeanPostProcessors()) {Object current processor.postProcessAfterInitialization(result, beanName);if (current null) {return result;}result current;}return result;}方法解读看这里直接获取所有BeanPostProcessor 接口然后应用postProcessAfterInitialization()方法。这里有个空判断是接口要求这么做的。返回null表示不想继续执行剩余的BeanPostProcessor 接口
2.7 AbstractAutowireCapableBeanFactory#doCreateBean【实例化】入口包括后续的实例化过程 方法调用链由2.2的createBean调用过来 全路径org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#doCreateBean 方法注释AbstractAutowireCapableBeanFactory这个类的中心方法创建一个bean实例填充bean实例应用后处理器等等 源码很长就不截取了。在这里个方法里面主要干了4件事情
实例化推断构造方法、实例化BeanDefinition的后置处理属性注入实例化后、属性注入对的你没看错【实例化后】是在属性注入这个方法里面被调用的初始化
方法解读正如方法注释说的这里【创建一个bean实例填充bean实例应用后处理器】等等。这意味着在这里包含了【实例化】过程中剩余的【推断构造方法、实例化、BeanDefinition的后置处理、实例化后等】步骤。另外下一个章节会说的【IOC属性填充】、【IOC-Aware回调】、【IOC初始化】等阶段入口其实也是在这个方法中。
*2.8 AbstractAutowireCapableBeanFactory#createBeanInstance实例化 方法调用链由2.7的doCreateBean调用过来 全路径org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#createBeanInstance 方法注释AbstractAutowireCapableBeanFactory这个类的中心方法创建一个bean实例填充bean实例应用后处理器等等 源码如下 protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, Nullable Object[] args) {// 步骤一再次确保类已经被加载Class? beanClass resolveBeanClass(mbd, beanName);if (beanClass ! null !Modifier.isPublic(beanClass.getModifiers()) !mbd.isNonPublicAccessAllowed()) {throw new BeanCreationException(mbd.getResourceDescription(), beanName,Bean class isnt public, and non-public access not allowed: beanClass.getName());}// 步骤二使用Supplier创建对象Supplier? instanceSupplier mbd.getInstanceSupplier();if (instanceSupplier ! null) {return obtainFromSupplier(instanceSupplier, beanName);}// 步骤三工厂方法创建对象if (mbd.getFactoryMethodName() ! null) {return instantiateUsingFactoryMethod(beanName, mbd, args);}// Shortcut when re-creating the same bean...boolean resolved false;boolean autowireNecessary false;if (args null) {synchronized (mbd.constructorArgumentLock) {if (mbd.resolvedConstructorOrFactoryMethod ! null) {resolved true;autowireNecessary mbd.constructorArgumentsResolved;}}}if (resolved) {if (autowireNecessary) {return autowireConstructor(beanName, mbd, null, null);}else {return instantiateBean(beanName, mbd);}}// 步骤四推断构造方法Constructor?[] ctors determineConstructorsFromBeanPostProcessors(beanClass, beanName);if (ctors ! null || mbd.getResolvedAutowireMode() AUTOWIRE_CONSTRUCTOR ||mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {return autowireConstructor(beanName, mbd, ctors, args);}// Preferred constructors for default construction?ctors mbd.getPreferredConstructors();if (ctors ! null) {return autowireConstructor(beanName, mbd, ctors, null);}// 步骤五实例化return instantiateBean(beanName, mbd);}方法解读这里在实例化Bean的时候采用了多种方式。如
2.8.1 Supplier创建对象
Supplier直译供应商。 首先判断BeanDefinition中是否设置了Supplier如果设置了则调用Supplier的get()得到对象。得直接使用BeanDefinition对象来设置Supplier比如
AbstractBeanDefinition beanDefinition BeanDefinitionBuilder.genericBeanDefinition().getBeanDefinition();
beanDefinition.setInstanceSupplier(new SupplierObject() {Overridepublic Object get() {return new UserService();}
});
context.registerBeanDefinition(userService, beanDefinition);2.8.2 工厂方法创建对象
如果没有设置Supplier则检查BeanDefinition中是否设置了factoryMethod也就是工厂方法有两种方式可以设置factoryMethod比如 方式一
bean iduserService classcom.zhouyu.service.UserService factory-methodcreateUserService /对应的UserService类为
public class UserService {public static UserService createUserService() {System.out.println(执行createUserService());UserService userService new UserService();return userService;}public void test() {System.out.println(test);}}方式二
bean idcommonService classcom.zhouyu.service.CommonService/
bean iduserService1 factory-beancommonService factory-methodcreateUserService /对应的CommonService的类为
public class CommonService {public UserService createUserService() {return new UserService();}
}Spring发现当前BeanDefinition方法设置了工厂方法后就会区分这两种方式然后调用工厂方法得到对象。 值得注意的是我们通过Bean所定义的BeanDefinition是存在factoryMethod和factoryBean的也就是和上面的方式二非常类似Bean所注解的方法就是factoryMethodAppConfig对象就是factoryBean。如果Bean所所注解的方法是static的那么对应的就是方式一。
2.8.3 构造方法创建对象
RT。
2.9 AbstractAutowireCapableBeanFactory#autowireConstructor推断构造方法 方法调用链由2.7的createBeanInstance调用过来 全路径org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#autowireConstructor 方法注释推断构造方法并且创建对象。 代码好长我就不截取了。这里的代码看不看都还好主要还是理解流程跟原则就好。
如果一个类只有一个构造方法不管这个构造方法是有参还是无参Spring都会使用这个构造方法创建对象如果有多个构造方法则看有没有无参构造方法。因为无参构造方法有默认的含义若有则选择无参的构造方法创建对象如果有多个构造方法且没有无参则看构造方法上是否有Autowired注解有就选择没有就报错
额外的在推断构造方法逻辑中除开会去选择构造方法以及查找入参对象意外会还判断是否在对应的类中是否存在使用**Lookup注解**了方法。如果存在则把该方法封装为LookupOverride对象并添加到BeanDefinition中。
在实例化时如果判断出来当前BeanDefinition中没有LookupOverride那就直接用构造方法反射得到一个实例对象。如果存在LookupOverride对象也就是类中存在Lookup注解了的方法那就会生成一个代理对象。 Lookup注解就是方法注入使用demo如下
Component
public class UserService {private OrderService orderService;public void test() {OrderService orderService createOrderService();System.out.println(orderService);}Lookup(orderService)public OrderService createOrderService() {return null;}}2.10 AbstractAutowireCapableBeanFactory#applyMergedBeanDefinitionPostProcessorsBeanDefinition后置处理 方法调用链由2.7的doCreateBean调用过来 全路径org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#applyMergedBeanDefinitionPostProcessors 方法注释将MergedBeanDefinitionPostProcessors应用于指定的bean定义调用它们的postProcessMergedBeanDefinition方法。 源码如下
protected void applyMergedBeanDefinitionPostProcessors(RootBeanDefinition mbd, Class? beanType, String beanName) {for (MergedBeanDefinitionPostProcessor processor : getBeanPostProcessorCache().mergedDefinition) {processor.postProcessMergedBeanDefinition(mbd, beanType, beanName);}}方法解读Bean对象实例化出来之后接下来就应该给对象的属性赋值了。在真正给属性赋值之前Spring又提供了一个扩展点即当前的MergedBeanDefinitionPostProcessors。这里的主要难点还是这种类型的BeanPostProcessor的应用场景可能才是大家比较关心的。那你们觉得这里的主要应用场景应该是什么呢其实按照Spring的生命周期来说他现在提供给你的拓展点只能是【实例化】阶段后的生命周期了毕竟过去已经发生的已经没办法改变。所以我们可以在这里干预【初始化】这个阶段如下示例
public static void main(String[] args) {AnnotationConfigApplicationContext context new AnnotationConfigApplicationContext(AppConfig.class);Object newUser context.getBean(user);System.out.println(newUser);
}// 声明bean
Component
public class User {private String name;public String getName() {return name;}public void setName(String name) {this.name name;}public void myInit() {System.out.println(这是我自己指定的初始化方法);}
}// 声明一个MergedBeanDefinitionPostProcessor然后改变了User这个Bean的初始化方法
Component
public class MyBeanPostProcessor implements MergedBeanDefinitionPostProcessor {Overridepublic void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class? beanType, String beanName) {if (beanName.equals(user)) {beanDefinition.setInitMethodName(myInit);}}
}PS在Spring源码中AutowiredAnnotationBeanPostProcessor就是一个MergedBeanDefinitionPostProcessor它的postProcessMergedBeanDefinition()中会去查找注入点并缓存在AutowiredAnnotationBeanPostProcessor对象的一个Map中injectionMetadataCache为依赖注入做准备。
2.11 AbstractAutowireCapableBeanFactory#populateBean属性注入包含实例化后
PS属性注入不是我们这里需要关注的地方但因为【实例化后】在这个方法里面所以就只能点进来了 方法调用链由2.7的doCreateBean调用过来 全路径org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#populateBean 方法注释使用来自bean定义的属性值在给定的BeanWrapper中填充bean实例属性填充/依赖注入。 populateBean中关键源码如下 if (!mbd.isSynthetic() hasInstantiationAwareBeanPostProcessors()) {for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {if (!bp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {return;}}}方法解读在处理完BeanDefinition后Spring又设计了一个扩展点InstantiationAwareBeanPostProcessor的postProcessAfterInstantiation()比如
Component
public class ZhouyuInstantiationAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor {Overridepublic boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {if (userService.equals(beanName)) {UserService userService (UserService) bean;userService.test();}return true;}
}上述代码就是对userService所实例化出来的对象进行处理。这个扩展点在Spring源码中基本没有怎么使用。估计是为了后面拓展做准备
方法总结后
以后可能不这么写了挺麻烦的。我这样圈关键方法跟链路的原因纯粹是想加深自己的印象我也不知道放出来给大伙看你们能否学习到什么。
三、实例化逻辑流程图 学习总结
学习了实例化的过程学习了实例化过程中用到的2种【Bean后置处理器】InstantiationAwareBeanPostProcessor和MergedBeanDefinitionPostProcessor以及他们内部的一些方法