zoukankan      html  css  js  c++  java
  • 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了,不需要任何其它操作

  • 相关阅读:
    JSP介绍
    Cookie和Session的原理及异同
    过滤器的使用
    JAVA 集合
    **JVM** 类加载机制
    *JAVA IO/NIO*
    jvm
    ioc
    spring问题总结
    aop详解
  • 原文地址:https://www.cnblogs.com/chz-blogs/p/12565783.html
Copyright © 2011-2022 走看看