Javaconfig bean overide不会考虑添加@DependsOn

时间:2013-10-16 08:35:59

标签: spring javabeans

通过扩展原始的@Configuration类来覆盖Javaconfig Bean,我想为新的Bean定义添加一个@DependsOn。

但是,这种依赖似乎不会被考虑在内。这是一个TestCase再现我的问题:

public class SpringTest {

@Test
public void testDependsOnTakenInAccount() {
    AnnotationConfigApplicationContext ctx2 = new AnnotationConfigApplicationContext(AConfig.class, CConfig.class);
    Assert.assertEquals("overriden", ctx2.getBean("bean"));
}

@Configuration
public static class AConfig {

    @Bean
    public Object bean() {
        return "not overriden";
    }

}

@Configuration
public static class CConfig extends AConfig {

    protected boolean isInitialized = false;

    @Bean
    public Void doInit() {
        isInitialized = true;

        return null;
    }

    @Bean
    @DependsOn("doInit")
    public Object bean() {
        if (!isInitialized) {
            throw new RuntimeException("Not initialized");
        }

        return "overriden";
    }

}

}

这是预期的行为吗?如果是,我如何在覆盖bean时添加依赖项?

2 个答案:

答案 0 :(得分:1)

对我来说似乎是一个错误。

在配置类中覆盖@Bean工厂方法时,父BeanDefinition获胜并在BeanFactory上注册,覆盖孩子。

因此,您无法使用注释配置bean(因为它将被覆盖)。

以下测试结果

  

预期:其中[doInit] GT;但是:< [otherBean]>

@RunWith(JUnit4ClassRunner.class)
public class DependOnTest {

    @Test
    public void testBeanDefinitionOverriding() {
        AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(Config.class);
        BeanDefinition bd = ctx.getBeanDefinition("bean");
        Assert.assertEquals("doInit", bd.getDependsOn()[0]);
    }

    @Configuration
    public static class ParentConfig {

        @Bean
        @DependsOn("otherBean")
        public String bean() {
            return "not overriden";
        }

        @Bean
        public String otherBean() {
            return "otherBean";
        }

    }

    @Configuration
    public static class Config extends ParentConfig {

        @Bean
        public String doInit() {
            return "doInit";
        }

        @Bean
        @DependsOn("doInit")
        public String bean() {
            return "overriding";
        }

    }
}

我认为问题始于ConfigurationClassParser:

    // recursively process the configuration class and its superclass hierarchy
    do {
        metadata = doProcessConfigurationClass(configClass, metadata);
    }
    while (metadata != null);

将覆盖方法的结果添加到CongurationClass.beanMethods

可以修复是否已经从ConfigurationClass.addBeanMethod()

中的超类添加了beanMethod
public void addBeanMethod(BeanMethod method) {
    // Check if already added a bean method from superclass 
    for (BeanMethod beanMethod : beanMethods) {
        if (beanMethod.getMetadata().getMethodName().equals(method.getMetadata().getMethodName()) &&
                !(beanMethod.getMetadata().getDeclaringClassName()).equals(method.getMetadata().getDeclaringClassName()))

            // log and return.
            return;
        }

    this.beanMethods.add(method);
}

答案 1 :(得分:0)

正如何塞·路易斯·马丁所指出的,这已被Spring团队确认为一个错误。

我的工作方式是:

@DependsOn("doInit")
@Bean
public Void notOverridingBean() {
    return null;
}

@Bean
public Object bean(Object notOverridingBean) {
    return "overriden";
}

另一种方法是在另一个@Configuration类中覆盖bean。