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)

4.1 @Import

导入一个类到IOC容器中

4.2 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类)”

4.3 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);

4.4 SpringFactoriesLoader

spring.factories文件示例:

# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=org.mybatis.spring.boot.autoconfigure.MybatisAutoConfiguration

这是mybatis对springboot自动装配的spring.factories,这样的话,通过这个文件就可以启动这个mybatis自动装配类MybatisAutoConfiguration了,不需要任何其它操作

SpringBoot源码分析(一)@SpringBootApplication解析

上一篇:富文本在移动端的显示,px替换为rem


下一篇:ios自动化测试之Java + testng +maven + appium 框架及脚本编写和运行