精华内容
下载资源
问答
  • 主要介绍了简单了解Spring循环依赖解决过程,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
  • 主要介绍了详解Spring Bean的循环依赖解决方案,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
  • Spring IOC循环依赖解决方案分析

    千次阅读 2018-03-11 13:28:09
    Spring IOC循环依赖解决方案分析这里Spring主要用了三层缓存来完成对循环依赖的实现。下面的属性来源于DefaultSingletonBeanRegistry类 /** Cache of singleton objects: bean name --> bean instance */ ...

    Spring IOC循环依赖解决方案分析

    这里Spring主要用了三层缓存来完成对循环依赖的实现。

    下面的属性来源于DefaultSingletonBeanRegistry类

    	/** Cache of singleton objects: bean name --> bean instance */
    	private final Map<String, Object> singletonObjects = new ConcurrentHashMap<String, Object>(64);
    
    	/** Cache of singleton factories: bean name --> ObjectFactory */
    	private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<String, ObjectFactory<?>>(16);
    
    	/** Cache of early singleton objects: bean name --> bean instance */
    	private final Map<String, Object> earlySingletonObjects = new HashMap<String, Object>(16);
    
    

    当获取一个类对象时,会调用这个方法

    protected Object getSingleton(String beanName, boolean allowEarlyReference) {
    		Object singletonObject = this.singletonObjects.get(beanName);
    		if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
    			synchronized (this.singletonObjects) {
    				singletonObject = this.earlySingletonObjects.get(beanName);
    				if (singletonObject == null && allowEarlyReference) {
    					ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
    					if (singletonFactory != null) {
    						singletonObject = singletonFactory.getObject();
    						this.earlySingletonObjects.put(beanName, singletonObject);
    						this.singletonFactories.remove(beanName);
    					}
    				}
    			}
    		}
    		return (singletonObject != NULL_OBJECT ? singletonObject : null);
    	}


    这里用到了上面的三层缓存。其中第一层是singletonObjects,首先会去看singletonObjects是否已经创建了一个对象。如果没有,那么从第二层缓存earlySingletonObjects提前曝光对象的缓存中获取;如果没有,那么最后从第三层缓存singletonFactories单实例工厂缓存中获取。当获取成功后,会把第三层缓存singletonFactories的bean去掉,加入到第二层缓存中。


    下面就用一个例子来具体分析循环依赖的问题。

    比如一个类A中有一个属性是B类,B类中有一个属性是A类,这时看Spring是怎么解决他们的相互依赖的。

    Spring注入一个类的大体步骤分为两部分,一是先完成对类的构造工作,二是会对类的属性进行设置和填充。

    首先Spring构造A类,通过AbstractAutowireCapableBeanFactory的doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args)方法中调用addSingletonFactory方法将A类曝光到singletonFactories中。

    addSingletonFactory(beanName, new ObjectFactory<Object>() {
    				public Object getObject() throws BeansException {
    					return getEarlyBeanReference(beanName, mbd, bean);
    				}
    			});

    这时完成A的构造后,需要填充B属性,继续第二步,发现B还没有构造,于是开始B流程的构造过程,构造的时候发现需要填充A,从第三层缓存singletonFactories中找到A(此时的A还没有完全构造完成,但是可以拿到A的一个引用),B拿到A的引用后,完成B自己的填充属性工作,完成初始化工作,把自己放到第一层缓存singletonObjects中。这时回到A的这边,在拿到B对象后,完成自己的填充属性工作。

    这就是Spring处理循环依赖基本的一些思路,有兴趣的同学可以自行研究一下相关的代码,还是比较有意思的,可以看到spring设计比较好的一些思路。


    展开全文
  • Spring Bean 循环依赖解决简单分析 本文Spring版本: 5.0.5.RELEASE 什么是循环依赖: 循环依赖其实就是循环引用,也就是两个或则两个以上的bean互相持有对方,最终形成闭环。比如A 依赖 B,B 又依赖 A;或者A...

    Spring Bean 循环依赖解决简单分析

    本文Spring版本:

    5.0.5.RELEASE

    什么是循环依赖:

         循环依赖其实就是循环引用,也就是两个或则两个以上的bean互相持有对方,最终形成闭环。比如A 依赖 B,B 又依赖 A;或者A依赖于B,B依赖于C,C又依赖于A。

    Spring 循环依赖的处理方式:

    ①构造器的循环依赖:这种依赖spring是处理不了的,直 接抛出BeanCurrentlylnCreationException异常。

    ②单例模式下的setter循环依赖:通过“三级缓存”处理循环依赖。

    ③非单例循环依赖:无法处理。

     

    Spring 如何解决单例Bean的循环依赖问题?

    利用三级缓存(DefaultSingletonBeanRegistry中定义)。

    singletonObjects

    用于存放完全初始化好的 bean,从该缓存中取出的 bean 可以直接使用
    earlySingletonObjects存放原始的 bean 对象(尚未填充属性)
    singletonFactories存放 bean对应的工厂对象(ObjectFactory)

     

    解决循环依赖加载bean的大致流程:

     

    判断缓存中是否有X:

    //DefaultSingletonBeanRegistry#getSingleton
    protected Object getSingleton(String beanName, boolean allowEarlyReference) {
        //singletonObjects 第一级缓存,BeanFactory的单例全存在singletonObjects中
        //保存的是已经初始化完全的单例
        Object singletonObject = this.singletonObjects.get(beanName);
                //isSingletonCurrentlyInCreation=true,代表beanName所代表的bean循环依赖了
        if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
            synchronized (this.singletonObjects) {
                //第二级缓存,保存的是未初始化完全的单例(只是实例化)
                singletonObject = this.earlySingletonObjects.get(beanName);
                //allowEarlyReference在当前场景下,默认为true
                if (singletonObject == null && allowEarlyReference) {
                    //第三级缓存,不是真的缓存,缓存的是生成二级缓存的工厂方法
                    ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
                    if (singletonFactory != null) {
                        //通过缓存singletonFactories中的对象工厂获取bean的对象
                        //如果有AOP,获取的会是代理对象
                        singletonObject = singletonFactory.getObject();
                        this.earlySingletonObjects.put(beanName, singletonObject);
                        this.singletonFactories.remove(beanName);
                    }
                }
            }
        }
        return singletonObject;
    }

    实例化bean之后,会把获取当前bean的方式放入到singletonFactories缓存:

    注意:Map<String, ObjectFactory<?>> singletonFactories

    该级缓存存放的并不是实例化的bean,而是一个ObjectFactory对象,它可以构造出对应的bean

    //AbstractAutowireCapableBeanFactory#doCreateBean
    boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
            isSingletonCurrentlyInCreation(beanName));
    if (earlySingletonExposure) {
        if (logger.isDebugEnabled()) {
            logger.debug("Eagerly caching bean '" + beanName +
                    "' to allow for resolving potential circular references");
        }
        //添加缓存
        addSingletonFactory(beanName, new ObjectFactory<Object>() {
            @Override
            public Object getObject() throws BeansException {
                return getEarlyBeanReference(beanName, mbd, bean);
            }
        });
    }

    当bean实例化完成之后,会被放到一级缓存singletonObjects中,用于被其他bean获取:

    //DefaultSingletonBeanRegistry#getSingleton#addSingleton
    protected void addSingleton(String beanName, Object singletonObject) {
        synchronized (this.singletonObjects) {
            this.singletonObjects.put(beanName, (singletonObject != null ? singletonObject : NULL_OBJECT));
            this.singletonFactories.remove(beanName);
            this.earlySingletonObjects.remove(beanName);
            this.registeredSingletons.add(beanName);
        }
    }

    为什么是三级缓存?

          好像使用 earlySingletonObjects 和 singletonObjects 两级缓存,一个存放早期对象,一个存放初始化完成后的对象,也能实现同样的功能,singletonFactories 好像显得有些多此一举。其实不是的,对于普通对象,确实只要返回刚创建完的早期对象就好了,但对于内部有被 AOP 增强的方法的对象,需要返回的是代理对象。我们可以看一下 ObjectFactory 匿名内部类里面调用的 getEarlyBeanReference 方法:

    //AbstractAutowireCapableBeanFactory
    protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {
        Object exposedObject = bean;
        if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
            for (BeanPostProcessor bp : getBeanPostProcessors()) {
                // SmartInstantiationAwareBeanPostProcessor 这个后置处理器会在返回早期对象时 
                // 被调用,如果返回的对象需要加强,那这里就会生成代理对象
                // 如果返回的对象需要AOP增强,那这里exposedObject 就会替换成代理对象的引用
             // 比如上图中的bean X 如果被AOP增强,那么bean Y 加载时获取的bean X 其实是X的代理对象 
                if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
                    SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
                    exposedObject = ibp.getEarlyBeanReference(exposedObject, beanName);
                }
            }
        }
        return exposedObject;
    }

    我们可以看到对于一般的对象,返回的就是传入的早期对象,但是对于内部有被 AOP 增强的方法的对象,会使用后置处理器返回一个代理对象。

    如果在解决循环依赖时生成了代理对象,那么 AbstractAutoProxyCreator 会把原对象放入一个 Map 中,这个 Map 的作用是防止同类对象被重复动态代理:

    //AbstractAutoProxyCreator
    public Object getEarlyBeanReference(Object bean, String beanName) {
    // 提前暴露代理对象的引用,是在postProcessAfterInitialization之前执行
        Object cacheKey = this.getCacheKey(bean.getClass(), beanName);
            if (!this.earlyProxyReferences.contains(cacheKey)) {
                this.earlyProxyReferences.add(cacheKey);
            }
    
            return this.wrapIfNecessary(bean, beanName, cacheKey);
    }
    //AbstractAutoProxyCreator
    //有些BeanPostProcessor提供对Bean的Wrap的操作,但是生命周期位于在set操作之后,避免重复代理
    public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
        if (bean != null) {
                Object cacheKey = getCacheKey(bean.getClass(), beanName);
                if (!this.earlyProxyReferences.contains(cacheKey)) {
                    return wrapIfNecessary(bean, beanName, cacheKey);
                }
            }
            return bean;
    }

    earlySingletonObjects作用是可以提升多次循环依赖加载的效率(singletonFactory.getObject() 不用多次执行),比如 X 依赖 Y, Y 依赖 X, Z 也依赖 X。Y 注入 X 时 earlySingletonObjects 已经通过 singletonFactory.getObject() 得到了原始X,这样加载Y时就不用再执行 singletonFactory.getObject() 构造 X 实例了,直接从earlySingletonObjects获取即可。

     

    展开全文
  • IDEA 循环依赖解决

    千次阅读 2020-06-23 12:23:07
    报错异常:Error:java: Annotation processing is not supported for module cycles. Please ensure that all modules from cycle [A,B] are excluded from ...这个情况就是出现了循环依赖,所以我们需要在Projec.

    报错异常: Error:java: Annotation processing is not supported for module cycles. Please ensure that all modules from cycle [A,B] are excluded from annotation processing

    在项目菜单栏找到Analyze —>Analyze->Analyze Module Dependencies

    这个情况就是出现了循环依赖,所以我们需要在Project Struture--->Modules--->Dependencies中删除不该出现的依赖模块

    展开全文
  • Springboot循环依赖解决办法

    千次阅读 2020-11-04 15:48:24
    } public class ClassB { @Autowired ClassA classA } 那如何解决循环依赖,当然最好的方法是重构你的代码,进行解耦,但是重构不是一时的事情,那就使用下面的方法: 第一种: 在你的配置文件中,在互相依赖的两...

    最近在使用Spingboot做项目的时候,在引入shiro
    后,启动项目一直报错  Error creating bean with name 'debtServiceImpl': Bean with name 'debtServiceImpl' has been injected into other beans [repayBillServiceImpl,investServiceImpl,receiveBillServiceImpl] 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.   后来在网上找了半天说是依赖循环,检查了一下代码,确实存在循环依赖的现象,但是项目快要上线,再去改代码逻辑是来不及了,于是各种找解决方案,终于算是找到了。 
      首先说一下什么是依赖循环,
    比如:我现在有一个ServiceA需要调用ServiceB的方法,那么ServiceA就依赖于ServiceB,那在ServiceB中再调用ServiceA的方法,就形成了循环依赖。Spring在初始化bean的时候就不知道先初始化哪个

    bean就会报错。

    public class ClassA {
    
        @Autowired
    
        ClassB classB;
    
    }
    
    
    public class ClassB {
    
        @Autowired
    
        ClassA classA
    
    }

      那如何解决循环依赖,当然最好的方法是重构你的代码,进行解耦,但是重构不是一时的事情,那就使用下面的方法: 

     第一种:  

    <bean id="ServiceDependent1" class="org.xyz.ServiceDependent1" lazy-init="true"> 
    
    <constructor-arg ref="Service"/> </bean>  
    
     <bean id="ServiceDependent2" class="org.xyz.ServiceDependent2" lazy-init="true"> 
    
    <constructor-arg ref="Service"/> </bean>   

    在你的配置文件中,在互相依赖的两个bean的任意一个加上lazy-init属性。  

    第二种:        

    @Autowired     
    
    @Lazy      
    
    private ClassA classA; 
    
       
    
    @Autowired 
    
    @Lazy      
    
    private ClassB classB;

    在你注入bean时,在互相依赖的两个bean上加上@Lazy注解也可以。 

    以上两种方法都能延迟互相依赖的其中一个bean的加载,从而解决循环依赖的问题。

    展开全文
  • IDEA中循环依赖解决方法

    千次阅读 2019-09-29 14:49:33
    循行程序是报错Annotation processing is not supported for module cycles. Please ensure that all modules from cycle 是你的...一、查找循环依赖  IDEA菜单栏中打开Analyze->Analyze Module Dependencies.....
  • 1. 什么是循环依赖循环依赖其实就是循环引用,也就是两个或则两个以上的bean互相持有对方,最终形成闭环。比如A依赖于B,B依赖于A我们直接上代码 先创建一个类ServiceA依赖于ServiceB,然后ServiceB又依赖于...
  • Spring Bean的循环依赖解决方案

    千次阅读 2020-02-12 17:12:11
    如果使用构造函数注入,则可能会创建一个无法解析的循环依赖场景。 什么是循环依赖 下面是我所遇到的情况,代码结构如下: SpringSecurity 配置类: @Configuration public class BrowserSecurityConfig ...
  • 循环依赖是指在A中引用B,B中引用C,而C中引用A,容器创建对象时会出现死循环。相关解决方案如下: 1 选择其一使其延迟加载,然后从上下文中获取AService类型的bean即可。 现有AService 和BService,都在对方...
  • IDEA 循环依赖解决方法

    千次阅读 2019-05-22 16:23:45
    今天编译项目的时候出现了上面的问题,检查了各个模块的pom.xml文件中的依赖关系没有发现有循环依赖的的问题。 二、解决方法 IDEA菜单栏中打开Analyze->Analyze Module Dependencies...看到有的模块被红色的标出来...
  • 安装了很多rpm,yum源是创建的本地源库,没有联网,但是却出现了依赖,于是乎按照提示,去下载对应的rpm包,进行安装,安装时,提示上面的rpm没有安装,这样两个,或者多个rpm就形成了一个循环依赖,导致哪一个都...
  • Js 中的循环依赖解决方案

    千次阅读 2018-10-13 17:48:10
    循环依赖就是相互依赖,实际项目中难免会遇到这种情况,(a.js 依赖 b.js , b.js 依赖 a.js) 尤其是现在都是模块化的工程,引用想用一个js文件必须先引入。 实际问题 举个例子: 左边是三个电阻(a.js),右边是...
  • 文章目录Spring IOC原理IOC原理:依赖注入(DI)的三种方式Spring-Bean循环依赖以及解决方式什么是循环依赖Spring怎么解决循环依赖原理Spring单例对象初始化过程三级缓存Spring为什么不使用两级缓存AOP使用AOP的目的...
  • maven多模块实现以及循环依赖解决

    万次阅读 2018-11-30 12:50:55
    1.项目拆分为微服务 订单服务被单独拆出 负责订单的下单取消退款等等 ...最外层pom.xml中 配置公共的基础依赖jar包,其他子模块会相应引入相同的jar order-api为暴露给comsumer调用的接口,service-order为...
  • idea中的循环依赖解决方法

    千次阅读 2019-09-18 16:35:21
    通过查看工程总的pom.xml可以看到工程各模块之间的依赖关系,各模块自己的pom.xml里配置的依赖顺序没有问题,也没有循环依赖。应该是自己在写单元测试时继承过一个Test基类,结果由于依赖关系原因Test不能被import...
  • 链接静态库循环依赖解决方法

    千次阅读 2013-09-26 09:05:34
    如果存在多个库文件之间的循环依赖,只有把相关的几个库文件循环写两遍,比如:xample: example.carm-linux-gcc $(CFLAGS) -I$(INCLUDE) -o example example.c -L$(LIBS) -lcv -lml -lcvaux -lstdc++ -lcxcore -lcv ...
  • 发现问题出在转换JSON的环节,出现死循环,如下为解决方法 Book类上面放入 @JsonIgnoreProperties(ignoreUnknown = true, value = {&amp;quot;hibernateLazyInitializer&amp;quot;, &amp;quot;...
  • Springboot循环依赖如何解决

    万次阅读 多人点赞 2019-03-26 13:59:52
    1. 循环依赖是什么? Bean A 依赖 B,Bean B 依赖 A这种情况下出现循环依赖。 Bean A → Bean B → Bean A 更复杂的间接依赖造成的循环依赖如下。 Bean A → Bean B → Bean C → Bean D → Bean E → Bean A 2. ...
  • Spring-bean的循环依赖以及解决方式

    万次阅读 多人点赞 2017-09-12 08:18:21
    本文主要是分析Spring bean的循环依赖,以及Spring的解决方式。 通过这种解决方式,我们可以应用在我们实际开发项目中。 什么是循环依赖? 怎么检测循环依赖 Spring怎么解决循环依赖 Spring对于循环依赖无法...
  • bean的实例化仅仅是获得了bean的实例,该bean仍在继续创建之中,之后在该bean实例的基础之上,还要做很多额外的操作,例如bean的属性填充、处理器的应用、bean的循环依赖解决等,今天我们就来分析下Spring是如何解决...
  • 主要介绍了详解Spring循环依赖解决方案,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
  • Spring如何解决循环依赖问题

    千次阅读 多人点赞 2020-12-09 02:23:10
    1、什么是循环依赖:类与类之间的依赖关系形成了闭环,就会导致循环依赖问题的产生。 2、循环依赖问题在Spring中主要...3、Spring解决的单例模式下的setter方法依赖注入引起的循环依赖问题,主要是通过两个缓存来解决
  • Spring循环依赖解决方式

    万次阅读 多人点赞 2018-04-20 08:28:33
    Spring怎么解决循环依赖4.基于构造器的循环依赖5.基于setter属性的循环依赖6.结束语1. 什么是循环依赖循环依赖其实就是循环引用,也就是两个或者两个以上的bean互相持有对方,最终形成闭环。比如A依赖于B,B依赖...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 246,784
精华内容 98,713
关键字:

循环依赖怎么解决