Spring Boot起步依赖源码分析(一)
上次说到EnableAutoConfigurationImportSelector.getCandidateConfigurations方法导入了META-INF/spring.factories配置文件,把配置信息封装到了一个List集合中,接下来看下这个方法在什么地方呗调用,这里交大家一个eclipse看源码的小技巧,在方法名上右键然后选择Open Call Hierarchy就可以快速找到什么地方调用了这个方法。
@Override
public String[] selectImports(AnnotationMetadata metadata) {
if (!isEnabled(metadata)) {
return NO_IMPORTS;
}
try {
AnnotationAttributes attributes = getAttributes(metadata);
List<String> configurations = getCandidateConfigurations(metadata,
attributes);
configurations = removeDuplicates(configurations);
Set<String> exclusions = getExclusions(metadata, attributes);
configurations.removeAll(exclusions);
configurations = sort(configurations);
recordWithConditionEvaluationReport(configurations, exclusions);
return configurations.toArray(new String[configurations.size()]);
}
catch (IOException ex) {
throw new IllegalStateException(ex);
}
}
这段代码需要跟大家分析分析了
1、getAttributes(metadata);获取到了@EnableAutoConfiguration(exclude={},excludeName={})注解上的exclude和excludeName
2、
Set<String> exclusions = getExclusions(metadata, attributes);
configurations.removeAll(exclusions);
通过这两行代码把我们不需要的自动装配的configure排除掉。接着configurations = sort(configurations);对起步依赖的启动项进行了排序,让配置项顺序注入IOC,后面做了一些记录操作,然后把处理好的配置集合装换成了String[]数组返回,为什么要转成数组呢?如果你有这个疑问,那么恭喜你,你又get到一项新技能,因为到这里配置文件已经彻底初始化完毕,后面对这个配置集合的操作,不会再有插入和删除,只会有迭代和随机插叙,而数组进行随机访问和迭代操作的速度是最快的。
获取到配置信息之后,spring boot会加载配置信息中的所有配置类,这里我们从配置信息中取一个比较熟悉的org.springframework.boot.autoconfigure.web.WebMvcAutoConfiguration,源码如下:
@Configuration
@ConditionalOnWebApplication
@ConditionalOnClass({ Servlet.class, DispatcherServlet.class,
WebMvcConfigurerAdapter.class })
@ConditionalOnMissingBean(WebMvcConfigurationSupport.class)
@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE + 10)
@AutoConfigureAfter(DispatcherServletAutoConfiguration.class)
public class WebMvcAutoConfiguration {
//......代码略
}
看到这,如果你熟悉spring4.x的条件注解的话,上面的代码应该就很情切了,这里还是简单提一下@Conditional根据满足某一个条件创建一个特定的Bean。比如说当一个jar包在一个类路径下时,自动配置一个或多个Bean,或者只有某个Bean被创建时才会创建另一个Bean。Spring Boot中将大量使用到进行一些自动配置。举个例子比如:
@ConditionalOnClass({ Servlet.class, DispatcherServlet.class,WebMvcConfigurerAdapter.class })
当我们的Jar依赖也就是有我们的环境中存在Servlet.class, DispatcherServlet.class,WebMvcConfigurerAdapter.class这几个类文件,即条件满足。
到这里,你应该就明白了,spring boot 高大上的自动配置起步依赖是怎么玩起来的,我们再来总结一下
1、spring boot启动时回去导入spring-boot-autoconfigure包下META-INF/spring.factories配置文件
2、根据XxxxAutoConfiguration配置类的条件注解@Conditional判断当前环境中是否满足XxxxAutoConfiguration的注解条件,如果满足,则自动向spring ioc 容器中注入bean