使用 Spring JavaConfig 的 bean 初始化图

Initialization map of beans using Spring JavaConfig

我有 AbstractParent class,带有自动装配变量 fieldChild class,扩展了 AbstractParent。在我的应用程序中,我需要 sub-classes of AbstractParent 的映射来实现策略模式。

我使用 Spring JavaConfig 初始化我的应用程序。这是配置的一部分 class:

    @Bean
    public String field() {
        return "Field of abstract parent class";
    }

    @Bean
    public Child child() {
        return new Child();
    }

    @Bean
    public HashMap<String, Object> initMap() {
        HashMap<String, Object> map = new HashMap<>();
        map.put("child", child());
        return map;
    }

但是从 HashMap 初始化后 child 有 non-initialized 字段。我发现一些有趣的事情。以下是我的测试部分:

@Before
public void setUp() {
    AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
    context.register(Config.class);
    context.refresh();
    child = context.getBean(Child.class);
    map = context.getBean(HashMap.class);
}
@Test
public void test() {
    assertNotNull(child.getField());
    System.out.println(child);
    AbstractParent childFromMap = map.get("child");
    System.out.println(childFromMap);
    assertNotNull(childFromMap);
    System.out.println(childFromMap.getField());
    assertNotNull(childFromMap.getField()); //FAIL =(
}

变量child有non-null字段,而变量childFromMap的字段为空。在 println 中我可以看到,它是两个不同的 objects。所以我有建议,object 不是在 Spring 的上下文中创建的地图。

所以我的问题是: 是否可以使用在 JavaConfig 中创建的 objects 填充地图?

下面是我的问题的完整代码,您可以copy\paste并重现它。

Class抽象父

import org.springframework.beans.factory.annotation.Autowired;

public abstract class AbstractParent {

    @Autowired
    protected String field;

    protected abstract void method();

    protected String getField() {
        return field;
    }
}

Class Child

public class Child extends AbstractParent{

   @Override
   protected void method() {
       System.out.println(field);
   }
}

测试配置和测试

import org.junit.Before;
import org.junit.Test;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;

import java.util.HashMap;
import java.util.Map;

import static org.junit.Assert.assertNotNull;

public class TestConfig {
private Child child;
private Map<String,AbstractParent> map;
static class Config {

    @Bean
    public String field() {
        return "Field of abstract parent class";
    }

    @Bean
    public Child child() {
        return new Child();
    }

    @Bean
    public HashMap<String, Object> initMap() {
        HashMap<String, Object> map = new HashMap<>();
        map.put("child",child());
        return map;
    }

}

@Test
public void test() {
    assertNotNull(child.getField());
    System.out.println(child);
    AbstractParent childFromMap = map.get("child");
    System.out.println(childFromMap);
    assertNotNull(childFromMap);
    System.out.println(childFromMap.getField());
    assertNotNull(childFromMap.getField());
}

@Before
public void setUp() {
    AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
    context.register(Config.class);
    context.refresh();
    child = context.getBean(Child.class);
    map = context.getBean(HashMap.class);
}

}

PS:这个问题被大量修改了。现在更抽象了

我通过向 Config class 添加注释 @Configuration 解决了问题。 Spring inter-bean 引用在没有此注释的情况下不起作用。当省略@Configuration时,@Bean方法以lite方式处理,所以调用此方法只是简单的java方法调用

Spring @Bean doc