栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java > SpringBoot

Spring Boot系列——Spring Boot如何启动

SpringBoot 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Spring Boot系列——Spring Boot如何启动

注解

写过Spring Boot都知道需要有一个入口类,就是本例子中的TutorialApplication,而这个类上面必不可上的需要有一个@SpringBootApplication注解。

点击进入该注解,我们可以发现其是一个复合注解,包括@SpringBootConfiguration、@EnableAutoConfiguration和@ComponentScan。

 @Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@documented @Inherited @SpringBootConfiguration @EnableAutoConfiguration @ComponentScan(excludeFilters = {
      @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
      @Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {

     @AliasFor(annotation = EnableAutoConfiguration.class)
   Class[] exclude() default {};     @AliasFor(annotation = EnableAutoConfiguration.class)
   String[] excludeName() default {};     @AliasFor(annotation = ComponentScan.class, attribute = "basePackages")
   String[] scanbasePackages() default {};     @AliasFor(annotation = ComponentScan.class, attribute = "basePackageClasses")   Class[] scanbasePackageClasses() default {};

}

@SpringBootConfiguration

该注解底层其实就是@Configuration注解。熟悉Spring的发展里程碑就知道这是Java Config的配置形式。

通过该注解修饰,表示该类是一个配置类。

@EnableAutoConfiguration

该注解其实也是一个复合注解。

 @Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@documented @Inherited @AutoConfigurationPackage @import(AutoConfigurationimportSelector.class)
public @interface EnableAutoConfiguration {

   String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";

     Class[] exclude() default {};     String[] excludeName() default {};

}

其实现也是通过类似@import的方式注入AutoConfigurationimportSelector类,并借助该类将所有符合条件的Configuration注解修饰的配置类加载到Spring Boot容器中。从classpath中搜索所有的meta-INF/spring.factories配置文件,将其中org.springframework.boot.autoconfigure.EnableAutoConfiguration对应配置项通过反射的形式实例化为标注了@Configuration和javaconfig形式的IOC容器配置类,然后汇总为一个并加载到ioc容器中。

image

@ComponentScan

这个注解就不需要多介绍了吧,其作用自动扫描加载符合条件的bean。

SpringApplication

从项目的入口第一个碰到的就是SpringApplication类。

@SpringBootApplication public class TutorialApplication {    public static void main(String[] args) {
        SpringApplication.run(TutorialApplication.class, args);
    }
}

进入该类的静态方法run,可以看到其在构造SpringApplication对象

public static ConfigurableApplicationContext run(Class[] primarySources,      String[] args) {   return new SpringApplication(primarySources).run(args);
}

进入SpringApplication构造方法,可以看到

public SpringApplication(ResourceLoader resourceLoader, Class... primarySources) {
   this.resourceLoader = resourceLoader;
   Assert.notNull(primarySources, "PrimarySources must not be null");
   this.primarySources = new linkedHashSet<>(Arrays.asList(primarySources));
   this.webApplicationType = deduceWebApplicationType();
   setInitializers((Collection) getSpringFactoriesInstances(
         ApplicationContextInitializer.class));
   setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
   this.mainApplicationClass = deduceMainApplicationClass();
}

主要做了如下几件事:

  • 加载Source,这里只有只有Application

image

  • 推断WebApplicationType,该枚举有三种类型NONE、SERVLET、REACTIVE。

  • 设置初始化器变量setInitializers,初始化后得到6个初始化变量,这些类在上面提到的spring.factories中可以找到

image

  • 设置监听器,与上面setInitializers实现类似,最终得到如下10个listeners

image

  • 最后推断带有main函数的所在类,即入口类,这里就是TutorialApplication

private Class deduceMainApplicationClass() {   try {
      StackTraceElement[] stackTrace = new RuntimeException().getStackTrace();      for (StackTraceElement stackTraceElement : stackTrace) {         if ("main".equals(stackTraceElement.getMethodName())) {            return Class.forName(stackTraceElement.getClassName());
         }
      }
   }   catch (ClassNotFoundException ex) {      // Swallow and continue
  }   return null;
}



作者:Jackie_Zheng
链接:https://www.jianshu.com/p/f225708caf9e


转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/235920.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号