We saw in the last tutorials how to load configuration classes using 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.
Let's understand this with an example.
Example
MainConfig
package com.logicbig.example;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
@Configuration
@Import(MyImportSelector.class)
public class MainConfig {
@Bean
ClientBean clientBean() {
return new ClientBean();
}
@Bean
AppBean appBean() {
return new AppBean("from main config ");
}
}
ClientBean
package com.logicbig.example;
import org.springframework.beans.factory.annotation.Autowired;
public class ClientBean {
@Autowired
private AppBean appBean;
public void doSomething() {
System.out.println(appBean.getMessage());
}
}
Implementing ImportSelector
package com.logicbig.example;
import org.springframework.context.annotation.ImportSelector;
import org.springframework.core.type.AnnotationMetadata;
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()};
}
}
}
Configurations to be selected by ImportSelector
package com.logicbig.example;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class MyConfig1 {
@Bean
AppBean appBean() {
return new AppBean("from config 1");
}
}
package com.logicbig.example;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class MyConfig2 {
@Bean
AppBean appBean() {
return new AppBean("from config 2");
}
}
Main class
package com.logicbig.example;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.*;
import org.springframework.core.type.AnnotationMetadata;
public class ImportSelectorPrecedenceDemo {
public static void main(String[] args) {
System.setProperty("myProp", "someValue");
ApplicationContext context =
new AnnotationConfigApplicationContext(
MainConfig.class);
ClientBean bean = context.getBean(ClientBean.class);
bean.doSomething();
}
}
Outputfrom main config
As seen above the main configuration took precedence over imported configurations when there are conflicts.
If we want our imported configurations (selected by ImportSelector) to take precedence over main configurations, then we should use DeferredImportSelector rather than ImportSelector.
Example ProjectDependencies and Technologies Used: - spring-context 6.2.12 (Spring Context)
Version Compatibility: 3.2.9.RELEASE - 6.2.12 Version compatibilities of spring-context with this example: Versions in green have been tested.
- JDK 25
- Maven 3.9.11
|