使用 Spring JavaConfig 的 bean 初始化图
Initialization map of beans using Spring JavaConfig
我有 AbstractParent
class,带有自动装配变量 field
和 Child
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方法调用
我有 AbstractParent
class,带有自动装配变量 field
和 Child
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方法调用