Question

My situation is that the class name of a bean can be configured by an external properties-file. It's fine to do this with XML

  <bean id="myService" class="${app.serviceClass}" />

and properties-file

app.serviceClass=com.example.GreatestClassThereIs

I tried to convert it to Java using a BeanFactoryPostProcessor:

@Configuration
public class MyConfiguration implements BeanFactoryPostProcessor {

  @Value("${app.serviceClass}")
  private String serviceClassName;

  @Override
  public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
    logger.warn("let's register bean of class " + serviceClassName + "...");
    GenericBeanDefinition beanDefinition = new GenericBeanDefinition();
    beanDefinition.setBeanClassName(serviceClassName);

    BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
    registry.registerBeanDefinition("myService", beanDefinition);
    logger.warn("done " + beanDefinition);
  }
}

The problem is that the lifecycle of Spring hasn't yet set handled the @Value and serviceClassName is null. How do I get the property in there?

Was it helpful?

Solution

Why not simply define a new Bean in your ApplicationContext by using Class.forName() from the @Value injected into the @Configuration?

So something like this:

@Configuration
public class MyConfiguration
{

     @Value("${app.serviceClass}")
     private String serviceClassName;

     @Bean
     public Object myService()
     {
          return Class.forName(serviceClassName).newInstance();
     }
}

EDIT by sjngm (for better readability than in the comment):

     @Bean
     public MyInterface myService()
     {
        Class<?> serviceClass = Class.forName(serviceClassName);
        MyInterface service = MyInterface.class.cast(serviceClass.newInstance());
        return service;
     }
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top