I have AbstractParent
class with autowired variable field
and Child
class, that extends AbstractParent
. In my application I need map of sub-classes of AbstractParent
to implement strategy pattern.
I init my application using Spring JavaConfig. Here is part of config 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;
}
But after initialization child from HashMap has non-initialized field. I find some interesting thing. Below part of my test:
@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 =(
}
Variable child
has non-null field, while field of var childFromMap
equals null. In println I can see, that it's two different objects. So I have suggestion, that object for map created not in context of Spring.
So my question: Is it possible to populate map with objects, that was created in JavaConfig?
Below full code of my problem, you can copy\paste and reproduce it.
Class AbstractParent
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);
}
}
TestConfig and test
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: This question was heavily modified. Now it's more abstract
I solved problem by adding annotation @Configuration
to Config
class. Spring inter-bean references don't work without this annotation. When @Configuration
is omitted, @Bean
methods processed in lite mode, so invocation of this method is just simple java method invocation