我们上一节演示过@ImportSelector注解的用法,使用非常简单,只需要两个步骤:
1)自定义一个引入类,实现ImportSelector接口,并重写selectImports方法
public class ImportPerson3 implements ImportSelector {
@Override
public String[] selectImports(AnnotationMetadata annotationMetadata) {
return new String[]{"com.itzhimei.handle.Person3"};
}
}
这里返回的就是要加载到ioc的类,可以是一个或多个,指定的类要是类全限定类名,例如:”com.itzhimei.handle.Person3″}。
2)在配置类的@Import中引入自定义类
/**
* ImportSelector的使用
*/
@Import({ImportPerson3.class})
@Configuration
public class SpringBootConfiguration_5 {
}
如果仅仅是这样使用,其实使用@Configuration通过@Bean来new一个Person3,或者使用@Import直接引入Person3就可以了,没有必要去使用ImportSelector。
但是如果我们要注入的Bean,需要根据一些条件来判断,再决定注入哪个Bean,那么此时ImportSelector的作用就可以发挥出来了。
来看一个例子,比如我们的应用,需要根据不同的操作系统来加载对应操作系统的功能类,此时就需要在Bean注入的时候进行判断了,因为如果你的应用是部署在Linux系统中,应用启动去加载Windows对应的功能类,是没有用处的,还会持续的占用内存资源。
1、定义业务接口
package com.itzhimei.handle.importselector;
/**
* ImportSelector应用场景Demo
* 业务接口定义
*/
public interface OSService {
void doHandler();
}
2、定义业务接口Windows实现类
package com.itzhimei.handle.importselector;
/**
* ImportSelector应用场景Demo
* 业务接口Windows实现
*/
public class WindowsOSServiceImpl implements OSService{
@Override
public void doHandler() {
System.out.println("这是Windows业务处理类");
}
}
3、定义业务接口Linux实现类
package com.itzhimei.handle.importselector;
/**
* ImportSelector应用场景Demo
* 业务接口Linux实现
*/
public class LinuxOSServiceImpl implements OSService{
@Override
public void doHandler() {
System.out.println("这是Linux业务处理类");
}
}
4、定义ImportSelector的实现,基于当前操作系统来加载对应系统的处理类
package com.itzhimei.handle.importselector;
import org.springframework.context.annotation.ImportSelector;
import org.springframework.core.type.AnnotationMetadata;
/**
* ImportSelector应用场景Demo
* ImportSelector的实现,基于当前操作系统来加载对应系统的处理类
*/
public class OSServiceImportSelector implements ImportSelector {
@Override
public String[] selectImports(AnnotationMetadata annotationMetadata) {
String property = System.getProperty("os.name");
String className;
if(property.equals("Windows 10")) {
className = "com.itzhimei.handle.importselector.WindowsOSServiceImpl";
} else {
className = "com.itzhimei.handle.importselector.LinuxOSServiceImpl";
}
return new String[]{className};
}
}
/* 输出
com.itzhimei.handle.Person2
com.itzhimei.handle.Person3
Person4
【【【com.itzhimei.handle.importselector.WindowsOSServiceImpl】】】
org.springframework.boot.autoconfigure.AutoConfigurationPackages
org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration
*/
5、启动SpringBoot项目,查看实际加载的操作系统处理类
/**
* ImportSelector应用场景Demo
*/
@Import({OSServiceImportSelector.class})
@Configuration
public class SpringBootConfiguration_7 {
}
最后我们启动SpringBoot项目,从启动输出的日志,可以看到实际输出包含这一行:
com.itzhimei.handle.Person2
com.itzhimei.handle.Person3
Person4
【【【com.itzhimei.handle.importselector.WindowsOSServiceImpl】】】
org.springframework.boot.autoconfigure.AutoConfigurationPackages
org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration
我们重点标出来的:【【【com.itzhimei.handle.importselector.WindowsOSServiceImpl】】】
也就是我们当前是Windows系统,所以最后加载的是WindowsOSServiceImpl处理类。
我们再看实现接口的重写方法,方法selectImports(AnnotationMetadata annotationMetadata),默认就有一个入参,这是系统传递给我们的,可以使用这个方法的入参获取到@Import标注的Class的各种信息,包括其Class名称,实现的接口名称、父类名称、添加的其它注解等信息,通过这些额外的信息可以根据需要选择需要定义的Bean的Class名称。