前言:
前面一篇文章介绍了@Import注解,可以在@Configuration标注的Class上可以使用@Import引入其它的配置类,其实还可以引入org.springframework.context.annotation.ImportSelector实现类。
接口概况:
ImportSelector接口只定义了一个selectImports(),用于指定需要注册为bean的Class名称。当在@Configuration标注的Class上使用@Import引入了一个ImportSelector实现类后,会把实现类中返回的Class名称都定义为bean。
使用方式:
一.静态场景
举个例子,现在往Spring容器里注入两个已知的类,也就是静态注入场景。
现有一个接口,ProductService,还有A和B两种实现类。
@Interface
public interface ProductService {
void doSomething();
}
@Implements
A:
public class DomesticProductServiceImplimplements ProductService{
@Override
public void doSomething() {
System.out.println("domestic hello world");
}
}
B:
public class OverSeaProductServiceImplimplements ProductService {
@Override
public void doSomething() {
System.out.println("oversea hello world");
}
}
如上图,实现ImportSeletor在selectImports方法中注入自定义的类。
最后,在configuration加入ImportSelector
@Configuration
@Import(ImportSelectorA.class)
public class Configurations {
}
测试:
二.动态场景
上面的case其实和直接@Configuration+@Bean||@Configuration+@Import注解区别不大,ImportSelector更好用的还是在动态注册的场景上:扫描某package路径下所有实现A接口的实现类,并注入Spring环境中。
动态代码:
需要注意的是在@Configuration配置类上指明@ComponentScan扫描路径,才能够使用basePackages的annotationScan。
当然也可以使用别的方式,直接指定扫描类所在的包,如:
packageName=Class.forName(importingClassMetadata.getClassName()).getPackage().getName();
String[] basePackages=newString[] {packageName};
ClassPathScanningCandidateComponentProviderscanner=newClassPathScanningCandidateComponentProvider(false);
TypeFilterhelloServiceFilter=newAssignableTypeFilter(ProductService.class);
亦可。
为ImportSelector定义特定的注解
当我们觉得在@Configuration配置类上使用@Import(DynamicImportSelector.class)太麻烦,或者是需要在ImportSelector实现类中使用一些特定的配置时就可以考虑为ImportSelector实现类定义一个特定的注解,在该注解上使用@Import(DynamicImportSelector.class)。如下针对上面的DynamicImportSelector定义了一个@ProductServiceScan注解,用于扫描ProductService实现类。
注解:
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Import(DynamicImportSelector.class)
public @interface ProductServiceScan {
}
配置类:
@Configuration
@ProductServiceScan
public class Configurations {
}
如上图,亦可。
也可以指定Scan的路径:
@Configuration
@ProductServiceScan("spring.boot.core")
public class Configurations {
}
本文基于SpringBoot 2.0.0.M4&Spring 5.0版本。