TODAY Context 解决循环依赖

发布于: 2020年07月22日 22:05:47 | 分类: 轮子工厂 | 浏览: 21

什么是循环依赖

一个Bean A依赖了Bean B 刚好 Bean B又依赖了Bean A。 在初始化其中一个Bean时由于依赖了另外一个Bean则去获取另外一个Bean,但发现又依赖了刚刚那个Bean,又不得不去获取刚刚那个Bean。。。周而复始,造成了循环。再多一个BeanC也是一样,参与的Bean越多形成的越大。

如何解决?

在获取依赖Bean时不去初始化就行了,仅仅是获取实例,一层一层的退出循环。必须要知道是不是已经在初始化当前的Bean了。记录下来。

关键代码

public class StandardBeanFactory
        extends AbstractBeanFactory implements ConfigurableBeanFactory, BeanDefinitionLoader {

...
    /**
     * Prevent Cycle Dependency
     */
    private final HashSet<String> currentInitializingBeanName = new HashSet<>();

...
}

循环检测

在初始化Bean时,检测当前是否在初始化依赖的Bean,是的话就直接返回,终止循环

@Override
protected Object initializeBean(final Object bean, final BeanDefinition def) throws BeanInitializingException {
    final String name = def.getName();
    if (currentInitializingBeanName.contains(name)) {
        return bean;
    }
    currentInitializingBeanName.add(name);
    final Object initializingBean = super.initializeBean(bean, def);
    currentInitializingBeanName.remove(name);
    return initializingBean;
}

测试代码

package cn.taketoday.context.factory.cycle;

public class CycleDependencyTest {

    @Test
    public void testCycleDependency() {
        CandidateComponentScanner.getSharedInstance().clear();
        try (ApplicationContext applicationContext = new StandardApplicationContext()) {
            applicationContext.loadContext("cn.taketoday.context.factory.cycle");
            assertEquals(3, applicationContext.getBeanDefinitionCount());

            final BeanA beanA = applicationContext.getBean(BeanA.class);
            final BeanB beanB = applicationContext.getBean(BeanB.class);
            applicationContext.getBean(BeanC.class);

            assertEquals(beanA, beanB.beanA);
            assertEquals(beanB, beanA.beanB);
            assertEquals(beanB, beanB.beanB);
        }
    }

    @Singleton
    public static class BeanA {

        @Autowired
        BeanB beanB;
    }

    @Singleton
    public static class BeanB {
        @Autowired
        BeanA beanA;
        @Autowired
        BeanB beanB;
    }

    @Singleton
    public static class BeanC {
        BeanA beanA;
        BeanB beanB;
        int order;

        @Order(3)
        @PostConstruct
        public void init(BeanA beanA, BeanB beanB) {
            this.beanA = beanA;
            this.beanB = beanB;
            order = 2;
        }

        @Order(2)
        @PostConstruct
        public void init2(BeanA beanA) {
            assertEquals(this.beanA, beanA);
            assertEquals(order, 2);
            order = 3;
        }

        @Order(1)
        @PostConstruct
        public void init3(BeanC beanC) {
            assertEquals(this, beanC);
            assertEquals(order, 3);
        }
    }

    //    @Singleton
    //    public static class ConstructorCycleDependency1 {
    //        ConstructorCycleDependency2 two;
    //
    //        ConstructorCycleDependency1(ConstructorCycleDependency2 two) {
    //            this.two = two;
    //        }
    //    }
    //
    //    @Singleton
    //    public static class ConstructorCycleDependency2 {
    //        ConstructorCycleDependency1 one;
    //
    //        ConstructorCycleDependency2(ConstructorCycleDependency1 one) {
    //            this.one = one;
    //        }
    //    }

}

避免

应避免循环依赖发生在构造器注入。

标签: Java 编程 轮子
版权声明:本文为作者原创文章,转载时请务必声明出处并添加指向此页面的链接。
分享:
发表评论

目前您尚未登录,请 登录 后进行评论

评论信息