首页 > 编程语言 >spring源码-之解决循环依赖

spring源码-之解决循环依赖

时间:2023-04-13 09:57:23浏览次数:45  
标签:依赖 BeanCreationException mbd spring beanName instanceWrapper bean 源码 ex

Spring如何解决循环依赖

为了解决循环依赖,Spring 使用了三级缓存。一级缓存用于存储 bean 定义。二级缓存用于存放已经创建但还没有完全初始化的前期bean实例。三级缓存用于存放完全初始化的bean实例。

当检测到循环依赖时,Spring 会创建一个部分初始化的 bean 实例并将其存储在二级缓存中。这允许 Spring 通过将部分初始化的 bean 实例注入到依赖它的另一个 bean 中来解决循环依赖。一旦解决了循环依赖,Spring 就可以完全初始化 bean 实例并将其存储在三级缓存中。

核心源码来自 Spring 框架中的 AbstractAutowireCapableBeanFactory 类。此类负责创建和初始化 bean 实例。核心部分在doCreateBean 方法种,该方法在创建新 bean 实例时调用。

以下为部分代码

/d:/study/spring-framework/spring-beans/src/main/java/org/springframework/beans/factory/support/AbstractAutowireCapableBeanFactory.java
if (instanceWrapper == null) { // Check if instanceWrapper is null
    instanceWrapper = createBeanInstance(beanName, mbd, args); // instanceWrapper if it is null
}
Object bean = instanceWrapper.getWrappedInstance(); // Get the wrapped instance from the instanceWrapper
Class<?> beanType = instanceWrapper.getWrappedClass(); // Get the wrapped class from the instanceWrapper
if (beanType != NullBean.class) { // Check if the beanType is not NullBean
    mbd.resolvedTargetType = beanType; // Set the resolvedTargetType to the beanType
}

// Allow post-processors to modify the merged bean definition.
synchronized (mbd.postProcessingLock) { // Synchronize on the postProcessingLock
    if (!mbd.postProcessed) { // Check if the bean definition has not been post-processed
        try {
            applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName); // Apply post-processors to the merged bean definition
        }
        catch (Throwable ex) {
            throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                    "Post-processing of merged bean definition failed", ex); // Throw a BeanCreationException if post-processing fails
        }
        mbd.postProcessed = true; // Set the postProcessed flag to true
    }
}

// Eagerly cache singletons to be able to resolve circular references
// even when triggered by lifecycle interfaces like BeanFactoryAware.
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
        isSingletonCurrentlyInCreation(beanName)); // Check if early singleton exposure is allowed
if (earlySingletonExposure) { // If it is allowed
    if (logger.isTraceEnabled()) {
        logger.trace("Eagerly caching bean '" + beanName +
                "' to allow for resolving potential circular references"); // Log a message indicating that the bean is being eagerly cached
    }
    addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean)); // Add a singleton factory for the bean
}

// Initialize the bean instance.
Object exposedObject = bean; // Set the exposedObject to the bean
try {
    populateBean(beanName, mbd, instanceWrapper); // Populate the bean with property values
    exposedObject = initializeBean(beanName, exposedObject, mbd); // Initialize the bean
}
catch (Throwable ex) { // Catch any exceptions that occur during initialization
    if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
        throw (BeanCreationException) ex; // If the exception is a BeanCreationException and the bean name matches, re-throw the exception
    }
    else {
        throw new BeanCreationException(
                mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex); // Otherwise, throw a new BeanCreationException
    }
}

标签:依赖,BeanCreationException,mbd,spring,beanName,instanceWrapper,bean,源码,ex
From: https://www.cnblogs.com/itqczzz/p/17312289.html

相关文章

  • springboot学习随笔
    1.大纲-springboot框架1.什么是Springboot以及Springboot的特点。2.快速搭建springboot项目3.springboot常用的配置文件类型.4.读取springboot配置文件的内容5.多环境配置6.springboot整合数据源。7.springboot整合mybatis.8.springboot整合定时器。2.Springbo......
  • spring事务里面开启线程插入,报错了是否会回滚?
    1.前言一道非常有意思的面试题目。大概是这样子的,如果在一个事务中,开启线程进行插入更新等操作,如果报错了,事务是否会进行回滚2.代码示例1@RequestMapping("/test/publish/submit")publicStringtestPublish1(){ log.info("start..."); transactionTemplate.execute(new......
  • 欢乐商城源码/品云购商城源码/英文版商城源码/全开源 可二开
    demo软件园每日更新资源,请看到最后就能获取你想要的:1.欢乐商城源码/品云购商城源码/英文版商城源码/全开源可二开商城源码/英文版商城源码/全开源可二开出海项目源码后台为中文语言页面效果:2.SQL学习指南(第2版)这是一本关于SQL的书,不是关于数据库的。以MySQL为例来......
  • SpringBoot向web容器注入Servlet,Filter及SpringSecurity注册DelegatingFilterProxy
    从SpringSecurity架构图可知SpringSecurity的过滤器与Web容器的过滤器是通过DelegatingFilterProxy接入的。由DelegatingFilterProxy代理了FilterChainProxy,FilterChainProxy包含了SpringSecurity的过滤器链。 那么DelegatingFilterProxy是怎么创建及如何加入到Web容器中? 看......
  • Springmvc常用注解参数与返回值
    1.常用注解1.1.@RequestMapping@RequestMapping注解是一个用来处理请求地址映射的注解,可用于映射一个请求或一个方法,可以用在类或方法上。标注在方法上用于方法上,表示在类的父路径下追加方法上注解中的地址将会访问到该方法@ControllerpublicclassHelloController{......
  • Springmvc入门
             1.什么是springmvcSpringWebMVC是一种基于Java的实现了MVC设计模式的、请求驱动类型的、轻量级Web框架。ssm:即springmvc,spring,mybatis  2.项目中加入springmvc支持2.1导入依赖<dependency><groupId>org.springframework</groupI......
  • Springboot三种启动方式
    在https://start.spring.io/上创建一个springboot工程生成的代码中的启动方式咱们暂时定义为默认方式:/***@auther:lawt*@date:2018/12/117*@Description:默认启动方式*/@SpringBootApplicationpublicclassMicroServicesSpringBootApplication{publicstaticv......
  • springboot 中的 classpath 指的是什么路径?
    classpath其本质其实是指项目打包后的classes下的路径,一般用来指代“src/main/resources”下的资源路径。通常会在各种配置文件中使用【classpath】关键字,例如:yml配置文件:WebMvcConfigurer配置类:......
  • springboot整合阿里云OSS实现多线程下文件上传(aop限制文件大小和类型)
    内容涉及:springboot整合阿里云oss自定义注解及aop的使用:对上传文件格式(视频格式、图片格式)、不同类型文件进行大小限制(视频和图片各自自定义大小)线程池使用:阿里云OSS多线程上传文件阿里云OSS分片上传大文件 业务需求需求一:前端传递单个或多个小文件(这里......
  • taro 3.0 官方模板运行报错 插件依赖 "@tarojs/plugin-platform-h5" 加载失败
    taroError:插件依赖"@tarojs/plugin-platform-h5"加载失败,请检查插件配置报错如下,原因:node版本的问题,使用nvm切换node版本就可以了......