简体   繁体   中英

Initialization map of beans using Spring JavaConfig

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

Spring @Bean doc

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM