目录
AutoConfigurationImportFilter作用
AutoConfigurationImportFilter源码
AutoConfigurationImportFilter原理分析
AutoConfigurationImportFilter实战之自定义Filter
四、在resources/META-INF下建立spring.factories文件
五、在resources下创建application.properties文件
AutoConfigurationImportFilter作用
提供给开发者的扩展接口,用于过滤spring.factories中自动配置类
AutoConfigurationImportFilter源码
/**
* 用来过滤自动配置类的扩展接口
* Filter that can be registered in {@code spring.factories} to limit the
* auto-configuration classes considered. This interface is designed to allow fast removal
* of auto-configuration classes before their bytecode is even read.
* <p>
* An {@link AutoConfigurationImportFilter} may implement any of the following
* {@link org.springframework.beans.factory.Aware Aware} interfaces, and their respective
* methods will be called prior to {@link #match}:
* 可以实现以下Aware接口,在执行match方法前执行Aware的回调方法
* <ul>
* <li>{@link EnvironmentAware}</li>
* <li>{@link BeanFactoryAware}</li>
* <li>{@link BeanClassLoaderAware}</li>
* <li>{@link ResourceLoaderAware}</li>
* </ul>
*
* @author Phillip Webb
* @since 1.5.0
*/
@FunctionalInterface
public interface AutoConfigurationImportFilter {
/**
* autoConfigurationClasses是自动配置全限定类名表示的数组,对应的返回值中元素为false时表示
* 过滤自动配置,反之不过滤
* Apply the filter to the given auto-configuration class candidates.
* @param autoConfigurationClasses the auto-configuration classes being considered.
* This array may contain {@code null} elements. Implementations should not change the
* values in this array.
* @param autoConfigurationMetadata access to the meta-data generated by the
* auto-configure annotation processor
* @return a boolean array indicating which of the auto-configuration classes should
* be imported. The returned array must be the same size as the incoming
* {@code autoConfigurationClasses} parameter. Entries containing {@code false} will
* not be imported.
*/
boolean[] match(String[] autoConfigurationClasses, AutoConfigurationMetadata autoConfigurationMetadata);
}
AutoConfigurationImportFilter原理分析
AutoConfigurationImportFilter用在AutoConfigurationImportSelector类中
private List<String> filter(List<String> configurations, AutoConfigurationMetadata autoConfigurationMetadata) {
long startTime = System.nanoTime();
// 候选的自动配置类
String[] candidates = StringUtils.toStringArray(configurations);
boolean[] skip = new boolean[candidates.length];
boolean skipped = false;
// 获取所有AutoConfigurationImportFilter接口实例并循环执行match方法,某个自动配置类只要在任何一个Filter中被过滤则被过滤
for (AutoConfigurationImportFilter filter : getAutoConfigurationImportFilters()) {
// 执行Aware回调
invokeAwareMethods(filter);
boolean[] match = filter.match(candidates, autoConfigurationMetadata);
for (int i = 0; i < match.length; i++) {
if (!match[i]) {
skip[i] = true;
candidates[i] = null;
skipped = true;
}
}
}
if (!skipped) {
return configurations;
}
List<String> result = new ArrayList<>(candidates.length);
// result中获取到剩下的的自动配置类
for (int i = 0; i < candidates.length; i++) {
if (!skip[i]) {
result.add(candidates[i]);
}
}
if (logger.isTraceEnabled()) {
int numberFiltered = configurations.size() - result.size();
logger.trace("Filtered " + numberFiltered + " auto configuration class in "
+ TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - startTime) + " ms");
}
return new ArrayList<>(result);
}
// 从spring.factories文件中获取AutoConfigurationImportFilter接口的所有实例
protected List<AutoConfigurationImportFilter> getAutoConfigurationImportFilters() {
return SpringFactoriesLoader.loadFactories(AutoConfigurationImportFilter.class, this.beanClassLoader);
}
AutoConfigurationImportFilter实战之自定义Filter
一、定义一个普通Java Bean
public class User {
public String getName() {
return "zhangsan";
}
}
二、定义一个自动配置类
@Configuration
public class MyAutoConfiguration {
/**
* 注册bean
*/
@Bean
public User user() {
return new User();
}
}
三、定义一个过滤器
public class MyConfigurationImportFilter implements AutoConfigurationImportFilter, EnvironmentAware {
private Environment environment;
/**
* 如果配置文件中my-auto-configuration.enabled值为true时,则装载MyAutoConfiguration自动配置类
*/
@Override
public boolean[] match(String[] autoConfigurationClasses, AutoConfigurationMetadata autoConfigurationMetadata) {
boolean[] matches = new boolean[autoConfigurationClasses.length];
for (int i = 0; i < matches.length; i++) {
// 当读取到MyAutoConfiguration自动配置类时, 如果配置文件中my-auto-configuration.enabled为true,则加载该自动配置类
matches[i] = MyAutoConfiguration.class.getName().equals(autoConfigurationClasses[i]) ? environment.getProperty("my-auto-configuration.enabled", Boolean.class, true) : true;
}
return matches;
}
@Override
public void setEnvironment(Environment environment) {
this.environment = environment;
}
}
四、在resources/META-INF下建立spring.factories文件
# Auto Configuration Import Filters
org.springframework.boot.autoconfigure.AutoConfigurationImportFilter=\
com.jspang582.springboot.autoconfigure.MyConfigurationImportFilter
# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.jspang582.springboot.autoconfigure.MyAutoConfiguration
五、在resources下创建application.properties文件
my-auto-configuration.enabled=true
六、测试效果
注意该类不要扫描到之前定义的自动配置类
@EnableAutoConfiguration
public class Test {
public static void main(String[] args) {
ConfigurableApplicationContext applicationContext = SpringApplication.run(Test.class, args);
User user = applicationContext.getBean(User.class);
System.out.println(user.getName());
}
}
当my-auto-configuration.enabled=true时,执行结果如下 :
当 my-auto-configuration.enabled=false时,执行结果如下:
执行结果符合预期