ImportSelector介绍
在@Configuration
标注的Class上可以使用@Import
引入其它的配置类,其实它还可以引入org.springframework.context.annotation.ImportSelector
实现类。ImportSelector接口只定义了一个selectImports()
,用于指定需要注册为bean的Class名称。当在@Configuration
标注的Class上使用@Import
引入了一个ImportSelector实现类后,会把实现类中返回的Class名称都定义为bean。来看一个简单的示例,假设现在有一个接口HelloService,需要把所有它的实现类都定义为bean,而且它的实现类上是没有加Spring默认会扫描的注解的,比如@Component
、@Service
等。
public interface HelloService {
void doSomething();
}
public class HelloServiceA implements HelloService {
@Override
public void doSomething() {
System.out.println("Hello A");
}
}
public class HelloServiceB implements HelloService {
@Override
public void doSomething() {
System.out.println("Hello B");
}
}
现定义了一个ImportSelector实现类HelloImportSelector,直接指定了需要把HelloService接口的实现类HelloServiceA和HelloServiceB定义为bean。
public class HelloImportSelector implements ImportSelector {
@Override
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
return new String[] {
HelloServiceA.class.getName(), HelloServiceB.class.getName()};
}
}
然后定义了@Configuration
配置类HelloConfiguration,指定了@Import
的是HelloImportSelector。
@Configuration
@Import(HelloImportSelector.class)
public class HelloConfiguration {
}
这样当加载配置类HelloConfiguration的时候会一并把HelloServiceA和HelloServiceB注册为Spring bean。可以进行如下简单测试:
@ContextConfiguration(classes=HelloConfiguration.class)
@RunWith(SpringRunner.class)
public class HelloImportSelectorTest {
@Autowired
private List<HelloService> helloServices;
@Test
public void test() {
this.helloServices.forEach(HelloService::doSomething);
}
}
看到这里可能你会觉得其实它也没什么用,因为整一个ImportSelector实现类那么麻烦,还不如直接在HelloConfiguration中定义bean或者import。在不引入ImportSelector的情况下,下面的两种方式都可以达到相同的效果。
@Configuration
@Import({
HelloServiceA.class, HelloServiceB.class})
public class HelloConfiguration {
}
@Configuration
public class HelloConfiguration {
@Bean
public HelloServiceA