Spring - Using DeferredImportSelector

[Updated: Dec 28, 2016, Created: Dec 27, 2016]

We saw in the last tutorial how to load configuration classes using ImportSelector.

The interface DeferredImportSelector extends ImportSelector.

The configuration class directly registered with the application context given preference over imported one. That means a bean of type T, configured in the main configuration will be used instead of a bean of the same type T from imported configuration. That applies to ImportSelector as well. On the other hand, DeferredImportSelector applies after all other configuration beans have been processed.

Let's see the difference between ImportSelector and DeferredImportSelector with an example.



Configuration order with ImportSelector

@Configuration
@Import(MyImportSelector.class)
public class MainConfig {

    @Bean
    ClientBean clientBean () {
        return new ClientBean();
    }

    @Bean
    AppBean appBean () {
        return new AppBean("from main config ");
    }
}
public class ClientBean {
    @Autowired
    private AppBean appBean;

    public void doSomething () {
        System.out.println(appBean.getMessage());
    }

}
public class MyImportSelector implements ImportSelector {

    @Override
    public String[] selectImports (AnnotationMetadata importingClassMetadata) {
        String prop = System.getProperty("myProp");
        if ("someValue".equals(prop)) {
            return new String[]{MyConfig1.class.getName()};
        } else {
            return new String[]{MyConfig2.class.getName()};
        }
    }
}
@Configuration
public class MyConfig1 {
    @Bean
    AppBean appBean () {
        return new AppBean("from config 1");
    }
}
@Configuration
public class MyConfig2 {
   @Bean
   AppBean appBean () {
       return new AppBean("from config 2");
   }
}
public class ImportSelectorExample {

public static void main (String[] args) {
    System.setProperty("myProp", "someValue");

    ApplicationContext context =
              new AnnotationConfigApplicationContext(
                        MainConfig.class);
    ClientBean bean = context.getBean(ClientBean.class);
    bean.doSomething();
}

Output

from main config


Configuration order with DeferredImportSelector

Now replace the implementing interface of MyImportSelector to DeferredImportSelector.

public class MyImportSelector implements DeferredImportSelector {
  ..
}

There's no other difference from the above example. This time we will have the following output:

from config 1



Example Project

Dependencies and Technologies Used :

  • Spring Context 4.3.4.RELEASE: Spring Context.
  • JDK 1.8
  • Maven 3.3.9

Spring Deferred Import Selector Select All Download
  • spring-deferred-import-selector
    • src
      • main
        • java
          • com
            • logicbig
              • example

See Also