有时候我们引入SpringBoot的Start组件的时候,默认就根据SPI机制加载了相应的自动配置的类;
比如通过META-INF下的spring.factories,来读取你需要默认引入的自动配置的类;
但是有时候你不想要这些功能,简单一点来说就是在启动类中过滤掉该类
@SpringBootApplication(exclude = {KafkaConsumerConfig.class})
这样启动的时候容器就会排除该类。
但是有时候要求可能会稍微复杂一点,比如我需要通过一个开关配置或者自定义规则来决定是否加载该类。
这个时候应该怎么去做?
SpringBoot中有一个针对SPI加载的类过滤接口名字叫AutoConfigurationImportFilter
这个类会在启动的时候通过SPI的机制回调,然后执行它的match方法来绝对目前SPI加载的类是否会被过滤掉;
这里简要的弄了一个这样的功能:
import org.springframework.boot.autoconfigure.AutoConfigurationImportFilter;
import org.springframework.boot.autoconfigure.AutoConfigurationMetadata;
import org.springframework.context.EnvironmentAware;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Component;
import java.util.*;
@Component
public class KafkaAutoConfigurationImportFilter implements AutoConfigurationImportFilter, EnvironmentAware {
private Environment environment;
/**
* 过滤的map
* K : 代表配置文件中的属性是否为true,如果为true的话就会过滤掉value中的值
* V : 过滤掉configuration的全路径
*/
private Map<String, String> filterAutoConfigurationMap = new LinkedHashMap<>();
public KafkaAutoConfigurationImportFilter() {
filterAutoConfigurationMap
.put("spring.kafka.consumer.multiple-group", "com.elab.core.kafka.config.KafkaConsumerConfig");
}
@Override
public void setEnvironment(Environment environment) {
this.environment = environment;
}
@Override
public boolean[] match(String[] autoConfigurationClasses, AutoConfigurationMetadata autoConfigurationMetadata) {
Set<String> filterClass = new HashSet<>();
// 获取配置文件中的属性名称的值,并决定是否过滤
filterAutoConfigurationMap.forEach((k, v) -> {
Boolean enableProperty = this.environment.getProperty(k, Boolean.class);
if (enableProperty) {
filterClass.add(v);
}
});
if (filterClass.size() > 0) {
boolean[] skip = new boolean[autoConfigurationClasses.length];
for (int i = 0; i < autoConfigurationClasses.length; i++) {
String autoConfigurationClass = autoConfigurationClasses[i];
if (!filterClass.contains(autoConfigurationClass)) {
skip[i] = true;
}
}
return skip;
}
return new boolean[0];
}
}
代码中会根据配置文件中的变量spring.kafka.consumer.multiple-group
得到的值是true还是false决定是否过滤掉com.elab.core.kafka.config.KafkaConsumerConfig
类;
这个时候需要在启动的时候引入它,可以在META-INF中新建一个spring.factories类然后加入内容:
org.springframework.boot.autoconfigure.AutoConfigurationImportFilter=com.elab.data.route.config.KafkaAutoConfigurationImportFilter
这个时候启动的时候就会回调该类,基于类中定义的规则来决定是否加载SPI中默认引用的类了;
想要了解运行流程可以查看org.springframework.boot.autoconfigure.AutoConfigurationImportSelector#filter
如有疑问,欢迎交流;
网友评论