精华内容
下载资源
问答
  • 2020-10-22 14:42:21

    @Autowired的what&how

    在spring框架下,我们可以通过@Autowired注解对属性或者方法参数进行标注,当spring ioc容器初始化时,会帮我们从容器中拿到对应的实例进行注入

    什么是循环依赖

    假如现在有两个Bean如下所示

    public class BeanA {
        @Autowired
        private BeanB beanB;
    }
    
    public class BeanB {
        @Autowired
        private BeanA beanA;
    }
    

    然后我们通过annotationConfigApplicationContext#register将两个bean的信息注入到容器中,最后通过refresh进行容器到初始化操作

    public static void main(String[] args) {
            AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext();
            annotationConfigApplicationContext.register(Bean1.class);
            annotationConfigApplicationContext.register(Bean2.class);
            annotationConfigApplicationContext.refresh();
        }
    

    可以看到A跟B互相依赖,试着想象:当容器先初始化beanA时,必然要对属性beanB进行赋值,这个时候容器中还没有beanB,那么势必会触发beanB的初始化流程,而beanB初始化的完成也需要对属性beanA赋值,但beanA还未初始化完成,这里就产生了所谓的循环依赖。

    spring如何解决循环依赖

    这里有一个很关键的属性:

    public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry {
    	/** Cache of singleton factories: bean name to ObjectFactory. */
    	private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);
    }
    

    key是beanName,value是一个对象工厂,我们点进去看一下

    public interface ObjectFactory<T> {
    
    	T getObject() throws BeansException;
    
    }
    

    其实这里的getObject()就是最终解决循环依赖所调用的方法。
    那么程序是怎样执行到这的呢?
    我们先从bean的创建入手
    如果容器还未实例化bean,那么就会走到这里

    protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
    			throws BeanCreationException {
    		BeanWrapper instanceWrapper = null;
    		if (instanceWrapper == null) {
    			//实例化bean,如果@Autowired加在构造方法上,
    			//那么就会在这里完成注入
    			//因为下面的回调还未注册,所以这里无法解决循环依赖
    			instanceWrapper = createBeanInstance(beanName, mbd, args);
    		}
    		
    		final Object bean = instanceWrapper.getWrappedInstance();
    		
    		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");
    			}
    			//往单例工厂(之前说的singletonFactories)中添加一个
    			//ObjectFactory的匿名实现作为回调,
    			addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
    			
    			//属性赋值,处理@Autowired(非构造方法)
    			populateBean(beanName, mbd, instanceWrapper);
    		}
    

    这里我们发现,在实例化bean跟对属性赋值之间有一个addSingletonFactory的操作,作用是注册一个可以获取当前正在创建的bean的一个回调

    	protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) {
    		synchronized (this.singletonObjects) {
    			if (!this.singletonObjects.containsKey(beanName)) {
    				this.singletonFactories.put(beanName, singletonFactory);
    			}
    		}
    	}
    

    进入回调,发现回调默认返回的就是bean本身

    	protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {
    		Object exposedObject = bean;
    		if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
    			for (BeanPostProcessor bp : getBeanPostProcessors()) {
    				if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
    					SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
    					exposedObject = ibp.getEarlyBeanReference(exposedObject, beanName);
    				}
    			}
    		}
    		return exposedObject;
    	}
    	
    	default Object getEarlyBeanReference(Object bean, String beanName) throws BeansException {
    		//	返回bean本身
    		return bean;
    	}
    

    ok,这里得出一个结论,即使bean未初始化完成,spring也提供了方法来获取这个bean的实例。
    如果应用到我们上面的栗子中来就是:

    1. beanA实例化完成
    2. 添加获取beanA的回调到singletonFactories
    3. 调用populateBean,处理@Autowired,注入beanB

    因为beanB还未创建,那么势必会进入创建beanB的流程,当beanB也走到populateBean时,也需要完成beanA的注入,这时就会尝试从beanFactory中获取beanA,这里最终会进到
    AbstractBeanFactorydoGetBean

    	protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
    			@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
    
    		final String beanName = transformedBeanName(name);
    		Object bean;
    
    		// Eagerly check singleton cache for manually registered singletons.
    		Object sharedInstance = getSingleton(beanName);
    	}
    

    这里很关键,进入getSingleton(beanName)

    	public Object getSingleton(String beanName) {
    		return getSingleton(beanName, true);
    	}
    	
    	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;
    	}
    

    当beanB走到这里时通过beanAbeanName获取beanA,首先会尝试从singletonObjects中获取,这里肯定获取不到,因为singletonObjectsput操作是在bean初始化完成之后。所以只能通过调用之前注册的回调singletonFactory.getObject()来获取beanA
    那么到此beanA注入到beanB的顺利完成,当beanB初始化完成之后,其实beanAgetBean()也就返回了beanB的引用,到此beanA也可以顺利完成依赖注入。

    更多相关内容
  • 这是一张三角形循环关系PPT图表,.PPTX格式;
  • 带箭头的双循环PPT关系图下载; 关键词:循环关系幻灯片图表,PPT关系图,PPT图表素材下载; 带箭头的双循环PPT关系图下载;关键词:循环关系幻灯片图表,PPT关系图,PPT图表素材下载;
  • 彩色循环关系信息可视化图标PPT模板循环关系图表
  • 三角循环关系PPT素材下载,关键词:三角形,循环结构,PPT素材下载,幻灯片图表素材,PPTX格式; 三角循环关系PPT素材下载,关键词:三角形,循环结构,PPT素材下载,幻灯片图表素材,PPTX格式;
  • 实用的smartart双循环关系幻灯片图表模板下载,关键词:并列关系,循环,围绕,smartart PowerPoint图表素材,.PPTX格式; 实用的smartart双循环关系幻灯片图表模板下载,关键词:并列关系,循环,围绕,smartart ...
  • 精美的3d立体水晶风格的循环关系PPT图表模板免费下载; 关键词:3d立体PPT图表素材,水晶风格,循环关系幻灯片图表模板,.PPTX格式; 精美的3d立体水晶风格的循环关系PPT图表模板免费下载;关键词:3d立体PPT图表...
  • 这是一张带白色小人的绿色循环关系PPT图表,第一PPT模板网提供幻灯片图表免费下载。 图表设计了立体绿色箭头的循环关系图,上方带有白色的小人,外侧有绿色的标签说明,适合用于制作节假日旅游行程安排PowerPoint的...
  • 两张循环关系PowerPoint图表免费下载。 关键词:循环关系,圆,圆环,流程图,幻灯片图表素材,.PPTX格式; 两张循环关系PowerPoint图表免费下载。关键词:循环关系,圆,圆环,流程图,幻灯片图表素材,.PPTX格式;
  • 循环关系表达式(for循环)

    千次阅读 2022-03-18 21:19:48
    计算机除了存储数据外,还可以做很多其他的工作。可以对数据进行分析、合并、重组、抽取、修改、推断、合成以及其他操作...这些程序控制语句通常都使用关系表达式和逻辑表达式来控制其行为。 for循环 很多情况下都...

            计算机除了存储数据外,还可以做很多其他的工作。可以对数据进行分析、合并、重组、抽取、修改、推断、合成以及其他操作。有时甚至会歪曲和破坏数据,不过我们应当尽量防止这种行为的发生。为了发挥其强大的操控能力,程序需要有执行重复的操作和进行决策的工具。当然,C++提供了这样的工具。事实上,它使用与常规C语言相同的 for循环、while循环、do while循环、if 语句和switch语句。这些程序控制语句通常都使用关系表达式和逻辑表达式来控制其行为。

    for循环

            很多情况下都需要程序执行重复的任务,如将数组中的元素累加起来或将歌颂生产的赞歌打印20份,C++中的 for循环可以轻松地完成这种任务。我们来看看下面的程序1中,以了解for循环所做的工作,然后讨论它是如何工作的。

    //forloop.cpp -- introducing the for loop
    
    #include <iostream>
    
    int main ()
    
    {
    
        using namespace std;
    
        int i;  // create a counter 
    
    //    initialize; test ; update
    
        for (i = 0; i < 5; i++)
    
            cout << "C++ knows loops.\n" ;
    
        cout <<"C++ knows when to stop .ln" ;
    
        return 0;
    
    }

    下面是该程序的输出:

    程序一

    该循环首先将整数变量i设置为0:

    i = o

    这是循环的初始化(loop initialization)部分。然后,循环测试(loop test)部分检查i是否小于5:

    i < 5

    如果确实小于5,则程序将执行接下来的语句——循环体(loop body):

    cout << "C++ knows loops.\n" ;

    然后,程序使用循环更新(loop update)部分将i加1:

    i++

        这里使用了++运算符——递增运算符(increment operator),它将操作数的值加1。递增运算符并不仅限于用于for循环。例如,在程序中,可以使用i++;来替换语句i=i+l;。将i加1后,便结束了循环的第一个周期。

        接下来,循环开始了新的周期,将新的i值与5进行比较。由于新值(1)也小于5,因此循环打印另一行,然后再次将i加1,从而结束这一周期。这样又进入了新的一轮测试、执行语句和更新i的值。这一过程将一直进行下去,直到循环将i更新为5为止。这样,接下来的测试失败,程序将接着执行循环后的语句。

    for循环的组成部分

        for循环为执行重复的操作提供了循序渐进的步骤。我们来具体看一看它是如何工作的。for 循环的组成部分完成下面这些步骤。

        1.设置初始值。

        2.执行测试,看看循环是否应当继续进行。

        3.执行循环操作。

        4.更新用于测试的值。

        C++循环设计中包括了这些要素,很容易识别。初始化、测试和更新操作构成了控制部分,这些操作由括号括起。其中每部分都是一个表达式,彼此由分号隔开。控制部分后面的语句叫作循环体,只要测试表达式为true,它便被执行:

    for (initialization; test-expression; update-expression)

            body

        C++语法将整个for看作一条语句——虽然循环体可以包含一条或多条语句。(包含多条语句时,需要使用复合语句或代码块,这将在本章后面进行讨论。)

        循环只执行一次初始化。通常,程序使用该表达式将变量设置为起始值,然后用该变量计算循环周期。

        test-expression(测试表达式)决定循环体是否被执行。通常,这个表达式是关系表达式,即对两个值进行比较。这个例子将i的值同5进行比较,看i是否小于5。如果比较结果为真,则程序将执行循环体。实际上,C++并没有将test-expression的值限制为只能为真或假。可以使用任意表达式,C++将把结果强制转换为bool类型。因此,值为0的表达式将被转换为bool值false,导致循环结束。如果表达式的值为非零,则被强制转换为 bool值 true,循环将继续进行。程序2通过将表达式i用作测试条件来演示了这一特点。更新部分的i--与i++相似,只是每使用一次,i值就减1。

    / / num_test.cpp -- use numeric test in for loop
    
    #include <iostream>
    
    int main ( )
    
    {
    
        using namespace std;
    
        cout << "Enter the starting countdown value: ";
    
        int limit ;
    
        cin >> limit ;
    
        int i;
    
        for (i = limit; i; i--)    //quits when i is o
    
            cout << "i = " << i << " \n" ;
    
        cout << "Done now that i = " << i << "\n" ;
    
        return 0 ;
    
    }

    该程序的输出:

    程序二

        注意,循环在i变为0后结束。

        关系表达式(如 i<5)是如何得到循环终止值0的呢?在引入 bool类型之前,如果关系表达式为true,则被判定为1;如果为 false,则被判定为0。因此,表达式3<5的值为1,而5<5的值为0。然而,C++添加了bool类型后,关系表达式就判定为bool字面值true和 false,而不是1和0了。这种变化不会导致不兼容的问题,因为C++程序在需要整数值的地方将把 true和false分别转换为1和0,而在需要bool值的地方将把0转换为false,非0转换为true。

        for 循环是入口条件(entry-condition)循环。这意味着在每轮循环之前,都将计算测试表达式的值,当测试表达式为false时,将不会执行循环体。例如,假设重新运行程序清单5.2中的程序,但将起始值设置为0,则由于测试条件在首次被判定时便为false,循环体将不被执行:

        update-expression(更新表达式)在每轮循环结束时执行,此时循环体已经执行完毕。通常,它用来对跟踪循环轮次的变量的值进行增减。然而,它可以是任何有效的C++表达式,还可以是其他控制表达式。这使for循环的功能不仅仅是从0数到5。

      然后今天就讲到这里啦,大家记得点赞收藏,分享转发,关注小哥哥哦! 最后,如果你想学或者正在学C/C++编程,可以加入我的编程学习C/C++俱乐部

    展开全文
  • 29套模板打包下载,含并列关系、循环关系、递进关系等图表
  • 循环,递进关系,圆角方形按钮图表,
  • 这是一张带白色小人的绿色循环关系PPT图表,第一PPT模板网提供幻灯片图表免费下载。 图表设计了立体绿色箭头的循环关系图,上方带有白色的小人,外侧有绿色的标签说明,适合用于制作节假日旅游行程安排PowerPoint的...
  • 带箭头的双循环PPT关系图下载; 关键词:循环,PPT关系图,PPT图表素材下载;
  • 实用的smartart双循环关系幻灯片图表模板下载,关键词:并列关系,循环,围绕,smartart PowerPoint图表素材.PPTX格式;
  • 1和0.9的循环关系

    千次阅读 2019-10-26 23:01:45
    由1/3引发的悖论 0.9的循环等于1 1/3 = 0.33333...(无限循环) ...如上的证明,1/3 乘以 3 等于 1, 而 0.3的循环乘以3得到的结果就是0.9的循环,那么 1 与 0.9的循环也是1. 0.9的循环不等于1 0.9的循环可以表示...

    由1/3引发的悖论

    0.9的循环等于1

    1/3 = 0.33333...(无限循环)
    1/3 * 3 = 1
    0.3333... * 3 = 0.99999...(无限循环)
    
    那么: 1 = 0.99999...(无限循环)
    

    如上的证明,1/3 乘以 3 等于 1, 而 0.3的循环乘以3得到的结果就是0.9的循环,那么 1 与 0.9的循环相等.

    0.9的循环不等于1

    0.9的循环可以表示为 0.9 + 0.09 + 0.009 + … + 0.00…009,由此:

    定义一个数列 a1 = 0.9,q = 0.1 的数列

    则有 a1 = 0.9, a2 = 0.09,a3 = 0.009

    于是有 Sn = 0.999999…(无限循环)= a1 + a2 +… + an

    由此,Sn = a1 (1 - qn) / (1 - q) = 0.9 ( 1 - 0.1n ) / (1 - 0.1) = 1 - 0.1n

    那么可以定义函数: f(x) = 1 - 0.1x

    可以作图:

    在这里插入图片描述

    由上图可知 f(x) 将无限趋近于 1,即 0.9的循环不等于1

    0.9的循环与1 产生的悖论

    综上所述,0.9的循环和1即相等,又不相等。感觉我的知识体系出现了问题,他们矛盾了。


    如果有错,欢迎指出。

    邮箱:ningmonguo@foxmail.com

    展开全文
  • 循环流程PPT关系图素材下载,关键词:循环,PPT文本框,商务人士PPT背景,循环关系PPT关系图,PPT流程图,幻灯片图表素材下载,PPTX格式; 循环流程PPT关系图素材下载,关键词:循环,PPT文本框,商务人士PPT背景,...
  • 两套循环箭头递进关系PPT图示下载
  • 论证了几种方法的相互关系,揭示了这些方法之间的内在联系.结果表明广义循环互相关法(GCCC)与循环相位谱法是等效的;信号选择性自适应法是循环谱相关法(SPECCORR)的迭代实现;循环互相关函数相关法(CCCC)和循环谱相干法...
  • 四项箭头并列图表,五角星五项循环图表,齿轮互动图表,项循环图表,粉笔手绘六项循环递进图表,树叶创意六项重复并列关系图表,立体感六项并列图表,花瓣创意六项并列关系图表,六项箭头循环递进图表,三项箭头递进...
  • 模糊关系的非循环

    2020-04-28 11:52:27
    通过讨论模糊关系的非循环性。研究内容包括一个模糊关系及其严格部分在一个t模T下的非循环性两部分。对模糊关系的非循环性,在T左连续下,借助α-截集和T-传递闭包,给出了T-非循环性的一些等价命题。在对模糊关系R的...
  • 三元素循环环绕PowerPoint说明图模板,关键词:循环关系PowerPoint模板下载,幻灯片图表模板下载,.PPTX格式; 三元素循环环绕PowerPoint说明图模板,关键词:循环关系PowerPoint模板下载,幻灯片图表模板下载,....
  • 为了研究不锈钢在循环荷载作用下的本构关系,对不锈钢S31608试件进行了多种循环加载试验,分析了不锈钢试件在单调荷载和循环荷载作用下的应力应变关系.采用Ramberg-Os-good模型对循环骨架曲线进行拟合,通过试验标定...
  • 什么是循环依赖以及解决方式

    万次阅读 多人点赞 2019-03-30 17:18:50
    1.什么是循环依赖? 它发生在bean A依赖于另一个bean B时,bean B依赖于bean A: 豆A→豆B→豆A 当然,我们可以有更多的暗示: 豆A→豆B→豆C→豆D→豆E→豆A 2.春天会发生什么 当Spring上下文加载所有bean时...

    1.什么是循环依赖?

    它发生在bean A依赖于另一个bean B时,bean B依赖于bean A:

    豆A→豆B→豆A

    当然,我们可以有更多的暗示:

    豆A→豆B→豆C→豆D→豆E→豆A

    2.春天会发生什么

    当Spring上下文加载所有bean时,它会尝试按照它们完全工作所需的顺序创建bean。例如,如果我们没有循环依赖,如下例所示:

    豆A→豆B→豆C.

    Spring将创建bean C,然后创建bean B(并将bean注入其中),然后创建bean A(并将bean B注入其中)。

    但是,当具有循环依赖时,Spring无法决定应该首先创建哪个bean,因为它们彼此依赖。在这些情况下,Spring将在加载上下文时引发BeanCurrentlyInCreationException

    使用构造函数注入时,它可能发生在Spring中; 如果您使用其他类型的注入,则不应该发现此问题,因为依赖项将在需要时注入,而不是在上下文加载时注入。

    3.一个快速示例

    让我们定义两个相互依赖的bean(通过构造函数注入):

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    @Component

    public class CircularDependencyA {

     

        private CircularDependencyB circB;

     

        @Autowired

        public CircularDependencyA(CircularDependencyB circB) {

            this.circB = circB;

        }

    }

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    @Component

    public class CircularDependencyB {

     

        private CircularDependencyA circA;

     

        @Autowired

        public CircularDependencyB(CircularDependencyA circA) {

            this.circA = circA;

        }

    }

    现在我们可以为测试编写一个Configuration类,让我们称之为TestConfig,它指定要扫描组件的基础包。假设我们的bean在包“ com.baeldung.circulardependency ” 中定义:

    1

    2

    3

    4

    @Configuration

    @ComponentScan(basePackages = { "com.baeldung.circulardependency" })

    public class TestConfig {

    }

    最后我们可以编写一个JUnit测试来检查循环依赖。测试可以为空,因为在上下文加载期间将检测循环依赖性。

    1

    2

    3

    4

    5

    6

    7

    8

    9

    @RunWith(SpringJUnit4ClassRunner.class)

    @ContextConfiguration(classes = { TestConfig.class })

    public class CircularDependencyTest {

     

        @Test

        public void givenCircularDependency_whenConstructorInjection_thenItFails() {

            // Empty test; we just want the context to load

        }

    }

    如果您尝试运行此测试,则会出现以下异常:

    BeanCurrentlyInCreationException: Error creating bean with name 'circularDependencyA':

    Requested bean is currently in creation: Is there an unresolvable circular reference?

    4.解决方法

    我们将展示一些最流行的方法来解决这个问题。

    4.1。重新设计

    如果您有循环依赖关系,则可能是您遇到了设计问题而且责任分离不清。您应该尝试正确地重新设计组件,以便它们的层次结构设计得很好,并且不需要循环依赖。

    如果您无法重新设计组件(可能有许多可能的原因:遗留代码,已经过测试且无法修改的代码,没有足够的时间或资源来完成重新设计......),有一些可行的解决方法。

    4.2。使用@Lazy

    打破循环的一个简单方法是让Spring懒洋洋地初始化其中一个bean。那就是:它不是完全初始化bean,而是创建一个代理将它注入另一个bean。注入的bean只有在第一次需要时才会完全创建。

    要使用我们的代码尝试此操作,您可以将CircularDependencyA更改为以下内容:

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    @Component

    public class CircularDependencyA {

     

        private CircularDependencyB circB;

     

        @Autowired

        public CircularDependencyA(@Lazy CircularDependencyB circB) {

            this.circB = circB;

        }

    }

    如果您现在运行测试,您将看到此次错误不会发生。

    4.3。使用Setter / Field Injection

    最流行的解决方法之一,也是Spring文档提出的,是使用setter注入。

    简单地说,如果你改变你的bean的连接方式,使用setter注入(或现场注入)而不是构造函数注入 - 这确实解决了这个问题。这样Spring就会创建bean,但是在需要之前不会注入依赖项。

    让我们这样做 - 让我们改变我们的类以使用setter注入,并将另一个字段(消息)添加到CircularDependencyB,以便我们可以进行适当的单元测试:

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    @Component

    public class CircularDependencyA {

     

        private CircularDependencyB circB;

     

        @Autowired

        public void setCircB(CircularDependencyB circB) {

            this.circB = circB;

        }

     

        public CircularDependencyB getCircB() {

            return circB;

        }

    }

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    @Component

    public class CircularDependencyB {

     

        private CircularDependencyA circA;

     

        private String message = "Hi!";

     

        @Autowired

        public void setCircA(CircularDependencyA circA) {

            this.circA = circA;

        }

     

        public String getMessage() {

            return message;

        }

    }

    现在我们必须对单元测试进行一些更改:

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    18

    19

    20

    21

    22

    23

    24

    @RunWith(SpringJUnit4ClassRunner.class)

    @ContextConfiguration(classes = { TestConfig.class })

    public class CircularDependencyTest {

     

        @Autowired

        ApplicationContext context;

     

        @Bean

        public CircularDependencyA getCircularDependencyA() {

            return new CircularDependencyA();

        }

     

        @Bean

        public CircularDependencyB getCircularDependencyB() {

            return new CircularDependencyB();

        }

     

        @Test

        public void givenCircularDependency_whenSetterInjection_thenItWorks() {

            CircularDependencyA circA = context.getBean(CircularDependencyA.class);

     

            Assert.assertEquals("Hi!", circA.getCircB().getMessage());

        }

    }

    以下解释了上面的注释:

    @Bean:告诉Spring框架必须使用这些方法来检索要注入的bean的实现。

    @Test:测试将从上下文中获取CircularDependencyA bean并断言其CircularDependencyB已正确注入,检查其message属性的值。

    4.4。使用@PostConstruct

    打破循环的另一种方法是在其中一个bean上使用@Autowired注入依赖项,然后使用@PostConstruct注释的方法来设置其他依赖项。

    我们的bean可以有以下代码:

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    @Component

    public class CircularDependencyA {

     

        @Autowired

        private CircularDependencyB circB;

     

        @PostConstruct

        public void init() {

            circB.setCircA(this);

        }

     

        public CircularDependencyB getCircB() {

            return circB;

        }

    }

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    @Component

    public class CircularDependencyB {

     

        private CircularDependencyA circA;

         

        private String message = "Hi!";

     

        public void setCircA(CircularDependencyA circA) {

            this.circA = circA;

        }

         

        public String getMessage() {

            return message;

        }

    }

    我们可以运行我们以前的相同测试,因此我们检查是否仍然没有抛出循环依赖性异常并且正确地注入了依赖项。

    4.5。实现ApplicationContextAwareInitializingBean

    如果其中一个bean实现ApplicationContextAware,则bean可以访问Spring上下文,并可以从那里提取其他bean。实现InitializingBean我们指出这个bean必须在设置了所有属性后执行一些操作; 在这种情况下,我们想手动设置我们的依赖项。

    我们的bean的代码是:

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    18

    19

    20

    21

    @Component

    public class CircularDependencyA implements ApplicationContextAware, InitializingBean {

     

        private CircularDependencyB circB;

     

        private ApplicationContext context;

     

        public CircularDependencyB getCircB() {

            return circB;

        }

     

        @Override

        public void afterPropertiesSet() throws Exception {

            circB = context.getBean(CircularDependencyB.class);

        }

     

        @Override

        public void setApplicationContext(final ApplicationContext ctx) throws BeansException {

            context = ctx;

        }

    }

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    @Component

    public class CircularDependencyB {

     

        private CircularDependencyA circA;

     

        private String message = "Hi!";

     

        @Autowired

        public void setCircA(CircularDependencyA circA) {

            this.circA = circA;

        }

     

        public String getMessage() {

            return message;

        }

    }

    同样,我们可以运行上一个测试,看到没有抛出异常并且测试按预期工作。

    5.结论

    在Spring中有很多方法可以处理循环依赖。首先要考虑的是重新设计bean,这样就不需要循环依赖:它们通常是可以改进的设计的症状。

    但是如果你的项目中绝对需要循环依赖,那么你可以遵循这里建议的一些解决方法。

    优选的方法是使用二次注射。但是还有其他选择,通常基于阻止Spring管理bean的初始化和注入,以及使用一种策略或另一种策略自己做。

    你可以找到上面显示的豆这里,和单元测试在这里

    展开全文
  • PPT文本框循环流程图下载,关键词:幻灯片文本框,PPT流程图,循环关系PPT图表素材下载,PPTX格式; PPT文本框循环流程图下载,关键词:幻灯片文本框,PPT流程图,循环关系PPT图表素材下载,PPTX格式;
  • 循环的PowerPoint图表模板下载,关键词:循环关系,环绕关系PPT图表模板,模板格式.PPTX; 循环的PowerPoint图表模板下载,关键词:循环关系,环绕关系PPT图表模板,模板格式.PPTX;
  • 3、循环控制器,和循环次数有点像,但是循环次数,是循环用户的操作,而循环控制器是循环挂在控制器下方的操作 二、用实例讲解 用例1、线程数量为1,循环次数为10,jmeter设置如下: 表示1111这账号,重复了...
  • 栈、递归、循环关系

    万次阅读 多人点赞 2017-01-31 15:22:28
    栈和递归其实原理都是差不多的,栈是先进后出,递归也是先进后出,递归也是利用堆栈来实现的,然后循环可以模拟代替栈和递归,只是用循环太复杂。但是它们的变量存储方式不同,导致占的空间不同。首先说明一下栈和堆...
  • 循环卷积和线性卷积的关系

    千次阅读 2021-01-19 19:33:29
    循环卷积和线性卷积的关系 x = [3 2 1 2 5]; y = [7 -1 8 5 1]; N = length(x) + length(y) - 1; x1 = [x zeros(1,N - length(x))]; y1 = [y zeros(1,N - length(y))]; c1 = ifft(fft(x1).*fft(y1));%频域的padding...
  • 递归与循环的互转关系

    千次阅读 2020-07-28 17:54:47
    递归与循环写法互转 1:递归与循环理论上可以互转 2:递归顺序必须由父–>子 -->兄弟; 3:循环用压栈方式可以实现由父–>子 -->兄弟;用连表方式可以实现父–>兄弟—>子的顺序; 递归通用模板 /** * ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 821,009
精华内容 328,403
关键字:

循环关系