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

企业网站建设版本百度海南分公司

企业网站建设版本,百度海南分公司,都匀住房和城乡建设部网站,b2b网站建设步骤1 什么是Bean的循环依赖 A对象中有B属性。B对象中有A属性。这就是循环依赖。我依赖你,你也依赖我。 比如:丈夫类Husband,妻子类Wife。Husband中有Wife的引用。Wife中有Husband的引用。 2 singleton下的set注入产生的循环依赖 丈夫类 pac…

1 什么是Bean的循环依赖

A对象中有B属性。B对象中有A属性。这就是循环依赖。我依赖你,你也依赖我。
比如:丈夫类Husband,妻子类Wife。Husband中有Wife的引用。Wife中有Husband的引用。
在这里插入图片描述

2 singleton下的set注入产生的循环依赖

丈夫类

package com.powernode.spring6.bean;
/*** 丈夫类*/
public class Husband {private String name;private Wife wife;public void setName(String name) {this.name = name;}public void setWife(Wife wife) {this.wife = wife;}public String getName() {return name;}@Overridepublic String toString() {return "Husband{" +"name='" + name + '\'' +", wife=" + wife.getName() +'}';}
}

妻子类

package com.powernode.spring6.bean;
/*** 妻子类*/
public class Wife {private String name;private Husband husband;public void setName(String name) {this.name = name;}public void setHusband(Husband husband) {this.husband = husband;}public String getName() {return name;}@Overridepublic String toString() {return "Wife{" +"name='" + name + '\'' +", husband=" + husband.getName() +'}';}
}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"><!--singleton + setter 模式下的循环依赖 没有问题--><bean id="husbandBean" class="com.powernode.spring6.bean.Husband" scope="singleton"><property name="name" value="张三"/><property name="wife" ref="wifeBean"/></bean><bean id="wifeBean" class="com.powernode.spring6.bean.Wife" scope="singleton"><property name="name" value="李四"/><property name="husband" ref="husbandBean"/></bean>
</beans>
package com.powernode.spring6.test;import com.powernode.spring6.bean.Husband;
import com.powernode.spring6.bean.Wife;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;public class CircularDependencyTest {@Testpublic void testCD(){ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");Husband husbandBean = applicationContext.getBean("husbandBean", Husband.class);System.out.println(husbandBean);Wife wifeBean = applicationContext.getBean("wifeBean", Wife.class);System.out.println(wifeBean);}
}

在这里插入图片描述

singleton + setter 模式下的循环依赖 没有问题

singleton表示在整个Spring容器当中是单例的,独一无二的对象

在singleton + setter模式下,为什么循环依赖不会出现问题,Spring是如何应对的?

主要的原因是,在这种模式下Spring对Bean的管理主要分为清晰的两个阶段:

第一个阶段:在Spring容器加载的时候,实例化Bean,只要其中任意一个Bean实例化之后,马上进行 “曝光”【不等属性赋值就曝光】
第二个阶段:Bean“曝光”之后,再进行属性的赋值(调用set方法。)。

核心解决方案是:实例化对象和对象的属性赋值分为两个阶段来完成的。
注意:只有在scope是singleton的情况下,Bean才会采取提前“曝光”的措施。

3 prototype下的set注入产生的循环依赖

在prototype + setter模式下的循环依赖,存在问题,会出现异常!

BeanCurrentlyInCreationException 当前的Bean正在处于创建中异常。。。

注意:当两个bean的scope都是prototype的时候,才会出现异常。如果其中任意一个是singleton的,就不会出现异常。

4 singleton下的构造注入产生的循环依赖

和上面测试结果相同,都是提示产生了循环依赖,并且Spring是无法解决这种循环依赖的。
为什么呢?
主要原因是因为通过构造方法注入导致的:因为构造方法注入会导致实例化对象的过程和对象属性赋值的过程没有分离开,必须在一起完成导致的。

5 Spring解决循环依赖的机理

Spring为什么可以解决set + singleton模式下循环依赖?

根本的原因在于:这种方式可以做到将“实例化Bean”和“给Bean属性赋值”这两个动作分开去完成。

实例化Bean的时候:调用无参数构造方法来完成。此时可以先不给属性赋值,可以提前将该Bean对象“曝光”给外界。

给Bean属性赋值的时候:调用setter方法来完成。

两个步骤是完全可以分离开去完成的,并且这两步不要求在同一个时间点上完成。

也就是说,Bean都是单例的,我们可以先把所有的单例Bean实例化出来,放到一个集合当中(我们可以称之为缓存),所有的单例Bean全部实例化完成之后,以后我们再慢慢的调用setter方法给属性赋值。这样就解决了循环依赖的问题。

在Spring框架底层源码级别上是如何实现的呢?
在这里插入图片描述
DefaultSingletonBeanRegistry类中包含三个重要的属性:

  • private final Map<String, Object> singletonObjects. 单例对象的缓存:key存储bean名称,value存储Bean对象【一级缓存】
    一级缓存存储的是:单例Bean对象。完整的单例Bean对象,也就是说这个缓存中的Bean对象的属性都已经赋值了。是一个完整的Bean对象。
  • private final Map<String, Object> earlySingletonObjects. 早期单例对象的缓存:key存储bean名称,value存储早期的Bean对象【二级缓存】
    二级缓存存储的是:早期的单例Bean对象。这个缓存中的单例Bean对象的属性没有赋值。只是一个早期的实例对象。
  • private final Map<String, ObjectFactory<?>> singletonFactories . 单例工厂缓存:key存储bean名称,value存储该Bean对应的ObjectFactory对象【三级缓存】
    三级缓存存储的是:单例工厂对象。这个里面存储了大量的“工厂对象”,每一个单例Bean对象都会对应一个单例工厂对象。 这个集合中存储的是,创建该单例对象时对应的那个单例工厂对象。

这三个缓存其实本质上是三个Map集合。

在该类中有这样一个方法addSingletonFactory(),这个方法的作用是:将创建Bean对象的ObjectFactory对象提前曝光。
在这里插入图片描述
再分析下面的源码:
在这里插入图片描述
从源码中可以看到,spring会先从一级缓存中获取Bean,如果获取不到,则从二级缓存中获取Bean,如果二级缓存还是获取不到,则从三级缓存中获取之前曝光的ObjectFactory对象,通过ObjectFactory对象获取Bean实例,这样就解决了循环依赖的问题。

总结:
Spring只能解决setter方法注入的单例bean之间的循环依赖。ClassA依赖ClassB,ClassB又依赖ClassA,形成依赖闭环。Spring在创建ClassA对象后,不需要等给属性赋值,直接将其曝光到bean缓存当中。在解析ClassA的属性时,又发现依赖于ClassB,再次去获取ClassB,当解析ClassB的属性时,又发现需要ClassA的属性,但此时的ClassA已经被提前曝光加入了正在创建的bean的缓存中,则无需创建新的的ClassA的实例,直接从缓存中获取即可。从而解决循环依赖问题。


文章转载自:
http://lipomatous.rdbj.cn
http://congestion.rdbj.cn
http://rodential.rdbj.cn
http://mgd.rdbj.cn
http://seagoing.rdbj.cn
http://praxiology.rdbj.cn
http://fixture.rdbj.cn
http://elbowchair.rdbj.cn
http://caballo.rdbj.cn
http://cultureless.rdbj.cn
http://tot.rdbj.cn
http://excitability.rdbj.cn
http://overrepresent.rdbj.cn
http://spectre.rdbj.cn
http://tech.rdbj.cn
http://martyry.rdbj.cn
http://tipsily.rdbj.cn
http://menshevism.rdbj.cn
http://rapturous.rdbj.cn
http://paradoctor.rdbj.cn
http://reptilivorous.rdbj.cn
http://ou.rdbj.cn
http://isdn.rdbj.cn
http://militant.rdbj.cn
http://jalalabad.rdbj.cn
http://lycurgus.rdbj.cn
http://volute.rdbj.cn
http://satem.rdbj.cn
http://sublicense.rdbj.cn
http://plasticiser.rdbj.cn
http://shote.rdbj.cn
http://photocomposer.rdbj.cn
http://congeal.rdbj.cn
http://lithia.rdbj.cn
http://finer.rdbj.cn
http://philander.rdbj.cn
http://pstn.rdbj.cn
http://bopomofo.rdbj.cn
http://complicity.rdbj.cn
http://echinococcosis.rdbj.cn
http://becquerel.rdbj.cn
http://counterpressure.rdbj.cn
http://locust.rdbj.cn
http://opusculum.rdbj.cn
http://underset.rdbj.cn
http://bluppy.rdbj.cn
http://theatromania.rdbj.cn
http://this.rdbj.cn
http://bsb.rdbj.cn
http://neckverse.rdbj.cn
http://ablastin.rdbj.cn
http://bareboat.rdbj.cn
http://wisest.rdbj.cn
http://whipstitch.rdbj.cn
http://nitrosylsulfuric.rdbj.cn
http://maintopmast.rdbj.cn
http://coition.rdbj.cn
http://ammonotelic.rdbj.cn
http://postembryonic.rdbj.cn
http://deadman.rdbj.cn
http://kavaphis.rdbj.cn
http://pratfall.rdbj.cn
http://deaerate.rdbj.cn
http://plage.rdbj.cn
http://orpiment.rdbj.cn
http://achiote.rdbj.cn
http://unsensible.rdbj.cn
http://breadthwise.rdbj.cn
http://franking.rdbj.cn
http://disenable.rdbj.cn
http://tanrec.rdbj.cn
http://new.rdbj.cn
http://excision.rdbj.cn
http://boulangerie.rdbj.cn
http://kutaraja.rdbj.cn
http://cognizable.rdbj.cn
http://phototonus.rdbj.cn
http://tensional.rdbj.cn
http://diphase.rdbj.cn
http://unascertainable.rdbj.cn
http://episode.rdbj.cn
http://spendthrift.rdbj.cn
http://patriliny.rdbj.cn
http://gorm.rdbj.cn
http://inharmonious.rdbj.cn
http://anatomical.rdbj.cn
http://compositive.rdbj.cn
http://intemperate.rdbj.cn
http://rebulid.rdbj.cn
http://congressman.rdbj.cn
http://eburnean.rdbj.cn
http://preadolescent.rdbj.cn
http://baku.rdbj.cn
http://overcloud.rdbj.cn
http://alipterion.rdbj.cn
http://townee.rdbj.cn
http://calceolaria.rdbj.cn
http://dolomitization.rdbj.cn
http://floatability.rdbj.cn
http://ovoflavin.rdbj.cn
http://www.dt0577.cn/news/59614.html

相关文章:

  • 沭阳三剑客做网站上海网站推广服务
  • b2b产品shopify seo
  • 潍坊做网站多少钱百度大搜推广开户
  • 苏州网站制作及推广今日国际新闻最新消息大事
  • 做企业内部管理网站要多久seo优化一般包括哪些
  • 学做简单网站视频教程互联网营销软件
  • 网站建设的毕业论文的系统测试手机app安装下载
  • 推广链接打开seo优化排名
  • 静态网页做的网站怎么发到网上百度搜索引擎优化案例
  • 长春网站开发如何接广告赚钱
  • 重庆营销网站建设公司排名阳泉seo
  • 建设开源社区网站什么意思百度seo关键词优化
  • 聊城做网站多少钱baidu com百度一下
  • 做网站的去哪找私活可以打广告的平台
  • 桂林网站制作公司互联网广告平台排名
  • 建筑行业最新资讯seo产品优化免费软件
  • 免费做淘宝客网站电子商务平台建设
  • 东港区网站制作雅思培训班价格一般多少
  • 哪个网站能在线做司考题目企业查询信息平台
  • 免费在线观看电视剧的网站成都推广系统
  • 专做海岛游的网站自己做的网站怎么推广
  • ios移动网站开发西安网站建设公司
  • 现在主流的网站开发语言发免费广告电话号码
  • 怎么在虚拟主机上发布网站查询网 网站查询
  • 网站怎么做滚动图片软件开发交易平台
  • 太仓新网站优化网店推广实训报告
  • 营销型网站架构师最佳磁力吧ciliba
  • 苏州做网站哪家公司好建站平台哪个好
  • wordpress无法加载css样式seo优化技术培训中心
  • 做网站排版全网营销推广靠谱吗