1

在通过扩展原始 @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 时添加依赖项?

4

2 回答 2

1

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

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

所以你不能用注释配置bean(因为它会被覆盖)。

以下测试结果

预期:<[doInit]> 但是是:<[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

可以修复检查 beanMethod 是否已经从超类中添加ConfigurationClass.addBeanMethod()

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);
}
于 2013-10-17T09:48:04.263 回答
0

正如 Jose Luis Martin 所指出的,这已被 Spring 团队确认为一个错误。

我已经解决了它:

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

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

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

于 2013-11-04T20:06:02.603 回答