简体   繁体   中英

Programmatically adding Beans to Spring application Context

I am trying to add a simple String to my Spring Application Context, and then autowire this to a different existing bean (A) within the application context. I know this is not the usual way to go, yet I need to add many beans programmatically, which would otherwise make my xml configuration huge.

public class MyPostProcessor implements BeanFactoryPostProcessor, Ordered {

  @Override
  public int getOrder() {
    return 0;
  }

  @Override
  public void postProcessBeanFactory(
        ConfigurableListableBeanFactory beanFactory) throws BeansException {
    beanFactory.registerSingleton("myString", "this is the String");
    A a = beanFactory.getBean(A.class);
    beanFactory.autowireBean(a);
  }
}    

public class A {

    @Autowired 
    public transient String message;

}

When running this, the property message of the instance of A is null. What am I missing?

EDIT: this is my application context:

@Configuration
class TestConfig {

  @Bean 
  public A a() {
    return new A();
  }

  @Bean
  public MyPostProcessor postProcessor() {
    return new MyPostProcessor();
  }

}

And this is my test:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = TestConfig.class)
public class MyTest {

  @Autowired 
  private transient A a;

  @Test
  public void test() throws Exception {
    System.err.println("Running");
    System.err.println("This is the autowired String: " + a.message);
    Thread.sleep(1000);
  }

}

Thanks

You should not instantiate beans from BeanFactoryPostprocessors . From BeanFactoryPostProcessor JavaDoc:

A BeanFactoryPostProcessor may interact with and modify bean definitions, but never bean instances. Doing so may cause premature bean instantiation, violating the container and causing unintended side-effects.

In your case, the A bean is instantiated before BeanPostProcessors and therefore not autowired.

Remove the lines:

A a = beanFactory.getBean(A.class);
beanFactory.autowireBean(a);

And will work.

Try using the @Qualifier to specific which bean you want to Auto wire.

public class A {

    @Autowired 
    @Qualifier("myString")
    public transient String message;

}

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