当前位置: 首页 > news >正文

spring源码篇(3)——bean的加载和创建

spring-framework 版本:v5.3.19

文章目录

  • bean的加载
  • bean的创建
  • 总结
    • getBean流程
    • createBean流程
      • doCreateBean流程

bean的加载

beanFactory的genBean最常用的一个实现就是AbstractBeanFactory.getBean()
以ApplicationContext为例,流程是: ApplicationContext.getBean()----》BeanFactory.getBean()----》AbstractBeanFactory.getBean()
在这里插入图片描述
而真正做事情的是deGetBean方法

protected <T> T doGetBean(String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)throws BeansException {//获取beanNameString beanName = transformedBeanName(name);Object beanInstance;//无论是什么作用域都先尝试从单例池获取Object sharedInstance = getSingleton(beanName);if (sharedInstance != null && args == null) {if (logger.isTraceEnabled()) {if (isSingletonCurrentlyInCreation(beanName)) {logger.trace("Returning eagerly cached instance of singleton bean '" + beanName +"' that is not fully initialized yet - a consequence of a circular reference");}else {logger.trace("Returning cached instance of singleton bean '" + beanName + "'");}}//有时候并不是放回实例本身,而是返回其映射的实例。如:BeanFactory情况下返回指定方法返回的实例beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, null);}else {//当原型模式下有循环依赖时,抛异常(原型模式下若存在循环依赖会导致内存泄漏)if (isPrototypeCurrentlyInCreation(beanName)) {throw new BeanCurrentlyInCreationException(beanName);}//尝试从父beanFactory加载beanBeanFactory parentBeanFactory = getParentBeanFactory();if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {String nameToLookup = originalBeanName(name);if (parentBeanFactory instanceof AbstractBeanFactory) {return ((AbstractBeanFactory) parentBeanFactory).doGetBean(nameToLookup, requiredType, args, typeCheckOnly);}else if (args != null) {return (T) parentBeanFactory.getBean(nameToLookup, args);}else if (requiredType != null) {return parentBeanFactory.getBean(nameToLookup, requiredType);}else {return (T) parentBeanFactory.getBean(nameToLookup);}}//如果不是仅仅做类型检查则是创建bean,这里进行记录if (!typeCheckOnly) {markBeanAsCreated(beanName);}StartupStep beanCreation = this.applicationStartup.start("spring.beans.instantiate").tag("beanName", name);try {if (requiredType != null) {beanCreation.tag("beanType", requiredType::toString);}//得到合并后的beanDefinitionRootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);//检查beanDefinition,抽象的beanDefinition会报错checkMergedBeanDefinition(mbd, beanName, args);//先加载dependsOn标注的beanString[] dependsOn = mbd.getDependsOn();if (dependsOn != null) {for (String dep : dependsOn) {//dePendsOn引起的循环依赖,抛异常if (isDependent(beanName, dep)) {throw new BeanCreationException(mbd.getResourceDescription(), beanName,"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");}//注册dependentBeanMap(dependsOn 于哪些bean)和注册dependenciesForBeanMap(被哪些bean dependOn)registerDependentBean(dep, beanName);try {getBean(dep);}catch (NoSuchBeanDefinitionException ex) {throw new BeanCreationException(mbd.getResourceDescription(), beanName,"'" + beanName + "' depends on missing bean '" + dep + "'", ex);}}}//-----------------------------------开始创建bean-----------------------------------------------//单例模式if (mbd.isSingleton()) {sharedInstance = getSingleton(beanName, () -> {try {return createBean(beanName, mbd, args);}catch (BeansException ex) {destroySingleton(beanName);throw ex;}});beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);}//原型模式else if (mbd.isPrototype()) {Object prototypeInstance = null;try {beforePrototypeCreation(beanName);prototypeInstance = createBean(beanName, mbd, args);}finally {afterPrototypeCreation(beanName);}beanInstance = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);}//其他模式else {String scopeName = mbd.getScope();if (!StringUtils.hasLength(scopeName)) {throw new IllegalStateException("No scope name defined for bean '" + beanName + "'");}Scope scope = this.scopes.get(scopeName);if (scope == null) {throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");}try {Object scopedInstance = scope.get(beanName, () -> {beforePrototypeCreation(beanName);try {return createBean(beanName, mbd, args);}finally {afterPrototypeCreation(beanName);}});beanInstance = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);}catch (IllegalStateException ex) {throw new ScopeNotActiveException(beanName, scopeName, ex);}}}catch (BeansException ex) {beanCreation.tag("exception", ex.getClass().toString());beanCreation.tag("message", String.valueOf(ex.getMessage()));cleanupAfterBeanCreationFailure(beanName);throw ex;}finally {beanCreation.end();}}//必要时进行类型转换return adaptBeanInstance(name, beanInstance, requiredType);}

bean的创建

从bean的加载中得知,当一个从缓存中获取不到的时候就会调用createBean方法去创建一个bean。而在AbstractBeanFactory中这是一个抽象方法,具体的创建逻辑由具体的beanFactory类自行实现。至少目前为止,spring内置的实现只有AbstractAutowireCapableBeanFactory.createBean()。无论是AnnotationConfigApplicationContext还是ClassPathXmlApplicationContext创建bean的逻辑最终都会来到这个方法。

虽然AnnotationConfigApplicationContext和ClassPathXmlApplicationContext并不直接继承AbstractAutowireCapableBeanFactory。但是都维护了一个DefaultListableBeanFactory成员变量,而这个成员变量继承自AbstractAutowireCapableBeanFactory。

createBean
在这里插入图片描述

doCreateBean

protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)throws BeanCreationException {//如果是单例,factoryBeanCache.removeBeanWrapper instanceWrapper = null;if (mbd.isSingleton()) {instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);}//实例化beanif (instanceWrapper == null) {instanceWrapper = createBeanInstance(beanName, mbd, args);}Object bean = instanceWrapper.getWrappedInstance();Class<?> beanType = instanceWrapper.getWrappedClass();if (beanType != NullBean.class) {mbd.resolvedTargetType = beanType;}//MergedBeanDefinitionPostProcessor的应用(如:AutowiredAnnotationBeanPostProcessor)synchronized (mbd.postProcessingLock) {if (!mbd.postProcessed) {try {applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);}catch (Throwable ex) {throw new BeanCreationException(mbd.getResourceDescription(), beanName,"Post-processing of merged bean definition failed", ex);}mbd.postProcessed = true;}}//提前暴露bean,循环依赖处理boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&isSingletonCurrentlyInCreation(beanName));if (earlySingletonExposure) {if (logger.isTraceEnabled()) {logger.trace("Eagerly caching bean '" + beanName +"' to allow for resolving potential circular references");}addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));}Object exposedObject = bean;try {//属性填充//填充属性之前会调用 InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation//填充属性之后会调用 InstantiationAwareBeanPostProcessor.postProcessProperties --如果返回null--> postProcessPropertyValuespopulateBean(beanName, mbd, instanceWrapper);//初始化bean(是指据配置自定义的初始化bean如:@PostConstruct,而不是指构造方法的初始化)//初始化之前会调用 PostProcessors.postProcessBeforeInitialization//初始化之后会调用 PostProcessors.postProcessAfterInstantiationexposedObject = initializeBean(beanName, exposedObject, mbd);}catch (Throwable ex) {if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {throw (BeanCreationException) ex;}else {throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);}}//循环依赖检查,判断是否需要抛出异常if (earlySingletonExposure) {Object earlySingletonReference = getSingleton(beanName, false);if (earlySingletonReference != null) {if (exposedObject == bean) {exposedObject = earlySingletonReference;}else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {String[] dependentBeans = getDependentBeans(beanName);Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);for (String dependentBean : dependentBeans) {if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {actualDependentBeans.add(dependentBean);}}if (!actualDependentBeans.isEmpty()) {throw new BeanCurrentlyInCreationException(beanName,"Bean with name '" + beanName + "' has been injected into other beans [" +StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +"] in its raw version as part of a circular reference, but has eventually been " +"wrapped. This means that said other beans do not use the final version of the " +"bean. This is often the result of over-eager type matching - consider using " +"'getBeanNamesForType' with the 'allowEagerInit' flag turned off, for example.");}}}}//注册DisposableBean,如果配置了destroy-methoy,这里需要注册以便于在销毁的时候调用try {registerDisposableBeanIfNecessary(beanName, bean, mbd);}catch (BeanDefinitionValidationException ex) {throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);}return exposedObject;}

initializeBean
在这里插入图片描述


总结

getBean流程

1:transformedBeanName(name) 转换为对应的beanName
2:getSingleton(beanName) 尝试从缓存中加载单例
3:isPrototypeCurrentlyIncreation(beanName) 原型模式的依赖检查
4:检测父BeanFactory
5:getMergedLocalBeanDefinition(beanName) GernericBeanDefinition转换为RootBeanDefinition
6:依赖检测
7:根据不同的模式创建bean
8:getObjectForBeanInstance(prototypeInstance, name, beanName, mbd) 根据得到的Bean获取真正对象
9:如果需要则做类型转换

createBean流程

1:锁定class
2:指定方法的覆盖
3:InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation
4:doCreateBean

doCreateBean流程

1:若为单例,移除factoryBeanCache内的缓存
2:实例化Bean
3:MergedBeanDefinitionPostProcessor.postProcessMergedBeanDefinition(如:AutowiredAnnotationBeanPostProcessor)
4:提前暴露bean,循环依赖处理

(populateBean)
5:InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation
6:属性填充
7:InstantiationAwareBeanPostProcessor.postProcessProperties --如果返回null–> postProcessPropertyValues

(initializeBean)
8:aware方法的执行(beanNameAware,beanClassLoaderAware,beanFactoryAware)
9:PostProcessors.postProcessBeforeInitialization
10:自定义初始化bean(如:InitializingBean.afterPropertiesSet,@PostConstruct,init-method)
11:PostProcessors.postProcessAfterInstantiation

12:循环依赖检查,判断是否需要抛出异常
13:注册DisposableBean

http://www.lryc.cn/news/30735.html

相关文章:

  • Spring 中事务的传播级别
  • ECharts可视化库--常用组件
  • openpnp - 设备开机后, 吸嘴校验失败的解决方法
  • 【Linux学习】基础IO——软硬链接 | 制作动静态库
  • 如何分辨on-policy和off-policy
  • 第三讲:ambari编译后的安装包制作流程说明
  • Python进阶-----面对对象6.0(绑定方法[类方法、静态方法]与内置方法)
  • java8四大基本函数式接口
  • Junit测试框架
  • 操作系统复习题
  • web项目的初始化
  • 29- 迁移学习 (TensorFlow系列) (深度学习)
  • 工具篇(五)炫酷排版,尽在LaTeX:让你的文档飞升吧!
  • 【蓝桥杯PythonB组备赛】【Acwing周赛】第93场 4867. 整除数 4868. 数字替换 python解
  • KNN学习报告
  • Java奠基】方法的讲解与使用
  • 字符串hash
  • 试题 算法训练 转圈游戏
  • 【uni-app教程】九、运行环境判断与跨端兼容
  • 扩展WSL2虚拟硬盘的大小
  • Win系统蓝牙设备频繁卡顿/断连 - 解决方案
  • Git学习入门(2)- 基本命令操作总结
  • SPringCloud:Nacos快速入门及相关属性配置
  • 医疗器械之模糊算法(嵌入式部分)
  • 网上销售笔记本系统
  • MySQL基础查询操作
  • English Learning - L2 语音作业打卡 小元音 [ʌ] [ɒ] Day9 2023.3.1 周三
  • Condition 源码解读
  • 看完这篇入门性能测试
  • 推导部分和——带权并查集