SpringBoot源码分析(一)@SpringBootApplication解析
@SpringBootApplication解析
三层注解
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = {
@Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
@ComponentScan
1.相当于 xml 配置文件中的context:component-scan,
2.ComponentScan 默认会扫描当前类所在 package 下的的所有加了相关注解标识的类到 IoC 容器中
3.主要作用就是扫描指定路径下的标识了需要装配的类,自动装配到 spring 的 Ioc 容器中。标识的形式主要是: @Component 、@Repository、 @Service、 @Controller 这类的注解标识的类。
4.就是这个东西扫描我们自己写的Bean
@SpringBootConfiguration
源码打开本质是个@Configuration,标明是配置类。(后面run方法会把自己传进去,本身其它注解才失效)
@EnableAutoConfiguration
是由两个注解形成:
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
再打开@AutoConfigurationPackage源码:
@Import(AutoConfigurationPackages.Registrar.class)
public @interface AutoConfigurationPackage {
}
总结:@EnableAutoConfiguration 等于
= @Import(AutoConfigurationPackages.Registrar.class)+@Import(AutoConfigurationImportSelector.class)
@Import
导入一个类到IOC容器中
AutoConfigurationPackages.Registrar
static class Registrar implements ImportBeanDefinitionRegistrar, DeterminableImports {
@Override
public void registerBeanDefinitions(AnnotationMetadata metadata,
BeanDefinitionRegistry registry) {
register(registry, new PackageImport(metadata).getPackageName());
}
@Override
public Set<Object> determineImports(AnnotationMetadata metadata) {
return Collections.singleton(new PackageImport(metadata));
}
}
其中registerBeanDefinitions方法,是为了注册bean==AutoConfigurationPackages类的,这个类保存了我们包扫描路径(com.xiaomi.项目名 这种,通过sb启动类Class信息拿到的),类注释说是 “用来存储自动配置包供以后的相关类使用(比如给JPA entity扫描器用来扫描开发人员通过注解@Entity定义的entity类)”
AutoConfigurationImportSelector
基于 ImportSelector 来实现基于动态 bean 的加载功能。 ImportSelector 接口的selectImports方法 返回的数组(类的全类名)都会被纳入到spring 容器中。
比较重要的是实现自DeferredImportSelector接口的方法selectImports
public String[] selectImports(AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotationMetadata)) {
return NO_IMPORTS;
}
AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader
.loadMetadata(this.beanClassLoader);
AutoConfigurationEntry autoConfigurationEntry = getAutoConfigurationEntry(
autoConfigurationMetadata, annotationMetadata);
return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
}
主要工作打到了getAutoConfigurationEntry方法里,一步步追查下去会发现在是在加载classpath路径下的META-INF/spring.factories文件里的类(SpringFactoriesLoader类的工作内容),这样是可扩展的,每个人都可以自己加这个文件自动装配。
剩余的代码就是 判断spring.factories文件里的类是否应该加载(有的设置了条件ConditionalOn)、去除重复的、冲突的等等 getAutoConfigurationEntry剩余代码如下:
configurations = removeDuplicates(configurations);
Set<String> exclusions = getExclusions(annotationMetadata, attributes);
checkExcludedClasses(configurations, exclusions);
configurations.removeAll(exclusions);
configurations = filter(configurations, autoConfigurationMetadata);
SpringFactoriesLoader
spring.factories文件示例:
# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.mybatis.spring.boot.autoconfigure.MybatisAutoConfiguration
这是mybatis对springboot自动装配的spring.factories,这样的话,通过这个文件就可以启动这个mybatis自动装配类MybatisAutoConfiguration了,不需要任何其它操作