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

免费网站建设制作视频杭州seo优化

免费网站建设制作视频,杭州seo优化,本地wordpress预览,wordpress 发布慢Spring循环依赖问题 什么是循环依赖问题示例项目结构项目代码运行结果 Async注解导致的问题使用Lazy注解解决Async注解导致的问题开启Aop使用代理对象示例项目结构项目代码运行结果 Spring是如何解决循环依赖问题的原理源码解读 什么情况下Spring无法解决循环依赖问题 什么是循…

Spring循环依赖问题

    • 什么是循环依赖问题
      • 示例
        • 项目结构
        • 项目代码
        • 运行结果
      • @Async注解导致的问题
      • 使用@Lazy注解解决@Async注解导致的问题
      • 开启Aop使用代理对象示例
        • 项目结构
        • 项目代码
        • 运行结果
    • Spring是如何解决循环依赖问题的
      • 原理
      • 源码解读
    • 什么情况下Spring无法解决循环依赖问题

什么是循环依赖问题

多个bean之间相互依赖,形成了一个闭环。 比如:A依赖于B、B依赖于C、C依赖于A

通常来说,如果问Spring容器内部如何解决循环依赖问题,一定是指默认的单例Bean中,属性相互引用的场景。也就是说,Spring的循环依赖,是Spring容器注入时出现的问题。

示例

项目结构

在这里插入图片描述

项目代码

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com</groupId><artifactId>spring-circular-dependency</artifactId><version>1.0-SNAPSHOT</version><properties><maven.compiler.source>8</maven.compiler.source><maven.compiler.target>8</maven.compiler.target></properties><dependencies><dependency><groupId>org.springframework</groupId><artifactId>spring-core</artifactId><version>5.2.1.RELEASE</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-beans</artifactId><version>5.2.1.RELEASE</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>5.2.1.RELEASE</version></dependency><dependency><groupId>org.aspectj</groupId><artifactId>aspectjrt</artifactId><version>1.8.9</version></dependency><dependency><groupId>org.apache.geronimo.bundles</groupId><artifactId>aspectjweaver</artifactId><version>1.6.8_2</version></dependency></dependencies></project>

Bean01.java

package com.spring.bean;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;/*** @author honey* @date 2023-08-23 17:50:53*/
@Component
public class Bean01 {@Autowiredprivate Bean02 bean02;
}

Bean02.java

package com.spring.bean;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;/*** @author honey* @date 2023-08-23 17:52:55*/
@Component
public class Bean02 {@Autowiredprivate Bean01 bean01;
}

SpringConfig01.java

package com.spring.config;import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;/*** @author honey* @date 2023-08-23 17:59:37*/
@Configuration
@ComponentScan(value = {"com.spring.bean"})
public class SpringConfig01 {
}

SpringTest01.java

package com.spring.test;import com.spring.bean.Bean01;
import com.spring.bean.Bean02;
import com.spring.config.SpringConfig01;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;/*** @author honey* @date 2023-08-23 18:00:24*/
public class SpringTest01 {public static void main(String[] args) {AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(SpringConfig01.class);Bean01 bean01 = applicationContext.getBean("bean01", Bean01.class);Bean02 bean02 = applicationContext.getBean("bean02", Bean02.class);System.out.println(bean01);System.out.println(bean02);}
}

运行结果

在这里插入图片描述

在这里插入图片描述

Spring默认情况下已经解决了循环依赖问题(单例Bean)

@Async注解导致的问题

在SpringConfig01类上加上@EnableAsync注解

在这里插入图片描述

在Bean01类中使用@Async注解修饰的异步方法

在这里插入图片描述

Bean01.java

package com.spring.bean;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;/*** @author honey* @date 2023-08-23 17:50:53*/
@Component
public class Bean01 {@Autowiredprivate Bean02 bean02;@Asyncpublic void test() {System.out.println(Thread.currentThread().getName() + "Bean01测试中...");}
}

运行结果

在这里插入图片描述

"C:\Program Files\Java\jdk1.8.0_191\bin\java.exe" "-javaagent:C:\Program Files\JetBrains\IntelliJ IDEA 2021.1.1\lib\idea_rt.jar=57456:C:\Program Files\JetBrains\IntelliJ IDEA 2021.1.1\bin" -Dfile.encoding=UTF-8 -classpath "C:\Program Files\Java\jdk1.8.0_191\jre\lib\charsets.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\deploy.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\ext\access-bridge-64.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\ext\cldrdata.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\ext\dnsns.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\ext\jaccess.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\ext\jfxrt.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\ext\localedata.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\ext\nashorn.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\ext\sunec.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\ext\sunjce_provider.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\ext\sunmscapi.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\ext\sunpkcs11.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\ext\zipfs.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\javaws.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\jce.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\jfr.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\jfxswt.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\jsse.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\management-agent.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\plugin.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\resources.jar;C:\Program Files\Java\jdk1.8.0_191\jre\lib\rt.jar;E:\知识点资料(第四年)\Spring源码解读\代码\spring-circular-dependency\target\classes;D:\maven_jar\org\springframework\spring-core\5.2.1.RELEASE\spring-core-5.2.1.RELEASE.jar;D:\maven_jar\org\springframework\spring-jcl\5.2.1.RELEASE\spring-jcl-5.2.1.RELEASE.jar;D:\maven_jar\org\springframework\spring-beans\5.2.1.RELEASE\spring-beans-5.2.1.RELEASE.jar;D:\maven_jar\org\springframework\spring-context\5.2.1.RELEASE\spring-context-5.2.1.RELEASE.jar;D:\maven_jar\org\springframework\spring-aop\5.2.1.RELEASE\spring-aop-5.2.1.RELEASE.jar;D:\maven_jar\org\springframework\spring-expression\5.2.1.RELEASE\spring-expression-5.2.1.RELEASE.jar;D:\maven_jar\org\aspectj\aspectjrt\1.8.9\aspectjrt-1.8.9.jar;D:\maven_jar\org\apache\geronimo\bundles\aspectjweaver\1.6.8_2\aspectjweaver-1.6.8_2.jar" com.spring.test.SpringTest01
八月 23, 2023 7:07:05 下午 org.springframework.context.support.AbstractApplicationContext refresh
警告: Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'bean01': Bean with name 'bean01' has been injected into other beans [bean02] 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 'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.
Exception in thread "main" org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'bean01': Bean with name 'bean01' has been injected into other beans [bean02] 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 'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:624)at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:517)at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:323)at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:321)at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202)at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:879)at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:878)at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:550)at org.springframework.context.annotation.AnnotationConfigApplicationContext.<init>(AnnotationConfigApplicationContext.java:89)at com.spring.test.SpringTest01.main(SpringTest01.java:15)Process finished with exit code 1

Spring在扫描bean发现某个类方法被@Async修饰时,会通过后置处理器AsyncAnnotationBeanPostProcessor生成代理对象,而该后置处理器的顺序比处理AOP的后置处理器还靠后,因此会导致Spring处理不了循环依赖。

使用@Lazy注解解决@Async注解导致的问题

在Bean01类中循环依赖的属性上使用@Lazy注解

在这里插入图片描述

运行结果

在这里插入图片描述

在这里插入图片描述

开启Aop使用代理对象示例

项目结构

在这里插入图片描述

项目代码

AspectAop.java

package com.spring.aop;import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;/*** @author honey* @date 2023-08-23 18:26:33*/
@Component
@Aspect
public class AspectAop {@Pointcut("execution (* com.spring.bean.*.*(..))")public void pointcut() {}@Around(value = "pointcut()")public Object doAround(ProceedingJoinPoint point) throws Throwable {System.out.println("doAround advice start");Object result = point.proceed();System.out.println("doAround advice end");return result;}
}

需要在Bean01和Bean02中加上一个普通方法,如:

在这里插入图片描述

package com.spring.bean;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;/*** @author honey* @date 2023-08-23 17:52:55*/
@Component
public class Bean02 {@Autowiredprivate Bean01 bean01;public void add() {}
}

SpringConfig01.java

package com.spring.config;import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;/*** @author honey* @date 2023-08-23 17:59:37*/
@Configuration
@ComponentScan(value = {"com.spring.bean", "com.spring.aop"})
@EnableAspectJAutoProxy
public class SpringConfig01 {
}

运行结果

在这里插入图片描述

在这里插入图片描述

Spring是如何解决循环依赖问题的

Spring底层通过三级缓存解决了循环依赖问题。

一级缓存:singletonObjects,也叫作单例池,存放已经经历了完整生命周期的Bean对象;

/** Cache of singleton objects: bean name to bean instance. */
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);

二级缓存:earlySingletonObjects,存放早期暴露出来的Bean对象,Bean的生命周期未结束(属性还未填充完整);

/** Cache of early singleton objects: bean name to bean instance. */
private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);

三级缓存:singletonFactories,存放可以生成Bean的工厂;

/** Cache of singleton factories: bean name to ObjectFactory. */
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);

原理

假设有两个对象分别是A和B,其中A依赖于B,B依赖于A

  1. 在创建A对象时需要B对象,于是将A对象存入三级缓存,再去创建B对象;
  2. 在创建B对象时发现需要A对象,于是先查一级缓存,没有,再查二级缓存,还是没有,再查三级缓存,找到了A对象,然后把三级缓存里面的A对象存入二级缓存,并删除三级缓存里面的A对象;
  3. B对象创建完成,将B对象存入一级缓存(此时B对象依赖的A对象依然是创建中状态),获取到B对象后回来接着创建A对象,直到创建完成,并将A对象存入一级缓存中(如果其它对象依赖于A对象和B对象,可以直接从一级缓存里面获取);

源码解读


在创建A对象时,A对象完成实例化后,会将A对象封装成ObjectFactory存入三级缓存。

AbstractBeanFactory.java

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

AbstractAutowireCapableBeanFactory.java

在这里插入图片描述
在这里插入图片描述

ObjectFactory.java

在这里插入图片描述

如果该对象是单例对象且开启了循环依赖且该对象正在创建中,则会将该对象封装成ObjectFactory对象存入三级缓存。其中ObjectFactory是一个函数接口,在调用getObject()方法时,才会真正去执行lambda语句调用getEarlyBeanReference()方法。

// 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));
if (earlySingletonExposure) {if (logger.isTraceEnabled()) {logger.trace("Eagerly caching bean '" + beanName +"' to allow for resolving potential circular references");}addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}

DefaultSingletonBeanRegistry.java

在这里插入图片描述


在为A对象设置属性时,发现A对象依赖于B对象,则会去尝试获取B对象,由于此时B对象还未被创建,所以B对象也会走和A对象一样的创建逻辑,不同的是在为B对象设置属性时,发现B对象依赖于A对象,可以从三级缓存中获取得到A对象。

AbstractBeanFactory.java

在这里插入图片描述

DefaultSingletonBeanRegistry.java

在这里插入图片描述

在这里插入图片描述

此时存入二级缓存的是不完整对象,调用singletonFactory.getObject()方法实际上是在调用getEarlyBeanReference(beanName, mbd, bean)方法。

在这里插入图片描述

在这里插入图片描述

如果是正常情况下,返回原始对象

InstantiationAwareBeanPostProcessorAdapter.java

在这里插入图片描述

如果是开启了Aop的情况下,返回Aop代理对象

AbstractAutoProxyCreator.java

在这里插入图片描述


将获取到的A对象设置为B对象的属性并执行完B对象的完整生命周期后,将B对象存入一级缓存中并从二级缓存、三级缓存中移除。此处也使用了ObjectFactory这个函数接口。

AbstractBeanFactory.java

在这里插入图片描述

DefaultSingletonBeanRegistry.java

在这里插入图片描述
在这里插入图片描述


获取得到B对象后,接着执行A对象的生命周期,执行完成后和B对象一样存入一级缓存中。


什么情况下Spring无法解决循环依赖问题

  1. 构造器注入的循环依赖问题;
  2. 非单例对象的循环依赖问题;

文章转载自:
http://dinncotroat.ssfq.cn
http://dinncodesmoid.ssfq.cn
http://dinncohygeia.ssfq.cn
http://dinncograb.ssfq.cn
http://dinncoreichspfennig.ssfq.cn
http://dinncotamarack.ssfq.cn
http://dinncopalliative.ssfq.cn
http://dinncometaplasia.ssfq.cn
http://dinncosquadron.ssfq.cn
http://dinncomead.ssfq.cn
http://dinncotrustworthily.ssfq.cn
http://dinncostickleback.ssfq.cn
http://dinncomousetrap.ssfq.cn
http://dinncoxylotile.ssfq.cn
http://dinncoisohyet.ssfq.cn
http://dinncobihar.ssfq.cn
http://dinncocampership.ssfq.cn
http://dinncofoliiferous.ssfq.cn
http://dinncoexcorticate.ssfq.cn
http://dinncobrunet.ssfq.cn
http://dinncoschlockmaster.ssfq.cn
http://dinncoinfusion.ssfq.cn
http://dinncobistort.ssfq.cn
http://dinncoflintstone.ssfq.cn
http://dinncotaylor.ssfq.cn
http://dinncoethic.ssfq.cn
http://dinncokishke.ssfq.cn
http://dinncofight.ssfq.cn
http://dinncoazure.ssfq.cn
http://dinncocardiectomy.ssfq.cn
http://dinncogoner.ssfq.cn
http://dinncovram.ssfq.cn
http://dinncorosehead.ssfq.cn
http://dinncoinfirmly.ssfq.cn
http://dinncounredressed.ssfq.cn
http://dinncomediumistic.ssfq.cn
http://dinncocuppy.ssfq.cn
http://dinncoairproof.ssfq.cn
http://dinncocadenced.ssfq.cn
http://dinncowallaceism.ssfq.cn
http://dinncoheliostat.ssfq.cn
http://dinncooxonian.ssfq.cn
http://dinncomultidialectal.ssfq.cn
http://dinncounauspicious.ssfq.cn
http://dinncosalvoconducto.ssfq.cn
http://dinncounbearable.ssfq.cn
http://dinncochanfron.ssfq.cn
http://dinncofifty.ssfq.cn
http://dinncovanadious.ssfq.cn
http://dinncoraticide.ssfq.cn
http://dinncoyestern.ssfq.cn
http://dinncokeelhaul.ssfq.cn
http://dinncoenamel.ssfq.cn
http://dinncopassee.ssfq.cn
http://dinncosomite.ssfq.cn
http://dinncodarlene.ssfq.cn
http://dinncocosher.ssfq.cn
http://dinncoeolienne.ssfq.cn
http://dinncodenunciate.ssfq.cn
http://dinncoembergoose.ssfq.cn
http://dinncomakhachkala.ssfq.cn
http://dinncorumania.ssfq.cn
http://dinncooutfoot.ssfq.cn
http://dinncohoarhound.ssfq.cn
http://dinncoliven.ssfq.cn
http://dinncoannelidan.ssfq.cn
http://dinncoovercorrect.ssfq.cn
http://dinncocauseless.ssfq.cn
http://dinncobear.ssfq.cn
http://dinncogail.ssfq.cn
http://dinnconeurotropism.ssfq.cn
http://dinncointeratomic.ssfq.cn
http://dinncosawney.ssfq.cn
http://dinncounscrupulously.ssfq.cn
http://dinncocarbuncled.ssfq.cn
http://dinncopompano.ssfq.cn
http://dinncoexobiology.ssfq.cn
http://dinncoborsch.ssfq.cn
http://dinncoamend.ssfq.cn
http://dinncoprincox.ssfq.cn
http://dinncofleeciness.ssfq.cn
http://dinncocalorimetrist.ssfq.cn
http://dinncoepispastic.ssfq.cn
http://dinncobelitoeng.ssfq.cn
http://dinncosuperatomic.ssfq.cn
http://dinncoraising.ssfq.cn
http://dinncowheezily.ssfq.cn
http://dinncouncomfortableness.ssfq.cn
http://dinncopursily.ssfq.cn
http://dinncocoalfield.ssfq.cn
http://dinncointromit.ssfq.cn
http://dinncopepper.ssfq.cn
http://dinncohydroforming.ssfq.cn
http://dinncodeepfry.ssfq.cn
http://dinncodefaecation.ssfq.cn
http://dinncomora.ssfq.cn
http://dinncooccultism.ssfq.cn
http://dinncolaudably.ssfq.cn
http://dinncochorology.ssfq.cn
http://dinncocerumen.ssfq.cn
http://www.dinnco.com/news/90592.html

相关文章:

  • 百度新闻源网站宁波seo网络推广渠道介绍
  • 免费网站制作软件有哪些网站的优化从哪里进行
  • 苏州网站公司排名前十湖南网站营销seo方案
  • 在线答题网站怎么做网络营销的基本特征
  • 深圳网站建设燦社区营销推广活动方案
  • 淄博网站制作营销广州网页制作
  • 清远医疗网站建设友链外链app
  • 网站建设项目招标标书北京seo软件
  • 网站委托书找谁做广告代理商
  • 如何创作个人网站中国时事新闻网
  • 网站审批分类达人介绍
  • 个人信息查询企业网站设计优化公司
  • 深圳app网站百度手机助手网页版
  • 网站设计有什么前景短期的技能培训有哪些
  • ajax网站模板提高关键词排名的软文案例
  • 怎么彻底删除2345网址导航网站seo优化心得
  • 网站管理后台地址山东免费网络推广工具
  • 微网站开发平台 知乎搜索引擎优化效果
  • 网站建设课程大纲娱乐热搜榜今日排名
  • 设计logo网站知乎灰色seo关键词排名
  • 担路网如何快速做网站每日新闻播报
  • 免费人物素材网站网页优化包括
  • 做外贸搜客户的网站google网页版登录入口
  • php做网站的源码西安百度推广网站建设
  • 采集做网站微指数查询
  • 网站支持asp国内做网站的公司
  • 杭州建委网站营销关键词有哪些
  • 武汉网页网站制作google推广 的效果
  • 网站建设合同注意爱站工具包手机版
  • 网站空间租用费用b站推广