• spring-boot 笔记


    spring-boot-starter:spring-boot 场景启动器。帮我们导入了 Web 模块正常运行所依赖的组件。Spring Boot 将所有的功能场景都抽取出来,做成许多启动器(starter),只需要在项目里面引入这些启动器,相关场景的所有依赖都会导入进来。要用什么功能就导入什么场景的启动器。

    @ConfigurationProperties(
    prefix = "spring.http"//①
    )
    public class HttpProperties {
     
     
    spring boot starter
     
    • @EnableScheduling是通过@Import将Spring调度框架相关的bean定义都加载到IoC容器。
    • @EnableMBeanExport是通过@Import将JMX相关的bean定义加载到IoC容器。

    而@EnableAutoConfiguration也是借助@Import的帮助,将所有符合自动配置条件的bean定义加载到IoC容器,仅此而已!

    @EnableAutoConfiguration自动配置的魔法骑士就变成了:从classpath中搜寻所有的META-INF/spring.factories配置文件,并将其中org.springframework.boot.autoconfigure.EnableutoConfiguration对应的配置项通过反射(Java Refletion)实例化为对应的标注了@Configuration的JavaConfig形式的IoC容器配置类,然后汇总为一个并加载到IoC容器。


    spring boot 的启动过程....

    SpringApplication的run方法的实现是我们本次旅程的主要线路,该方法的主要流程大体可以归纳如下:

    1) 如果我们使用的是SpringApplication的静态run方法,那么,这个方法里面首先要创建一个SpringApplication对象实例,然后调用这个创建好的SpringApplication的实例方法。在SpringApplication实例初始化的时候,它会提前做几件事情:

    • 根据classpath里面是否存在某个特征类(org.springframework.web.context.ConfigurableWebApplicationContext)来决定是否应该创建一个为Web应用使用的ApplicationContext类型。
    • 使用SpringFactoriesLoader在应用的classpath中查找并加载所有可用的ApplicationContextInitializer。
    • 使用SpringFactoriesLoader在应用的classpath中查找并加载所有可用的ApplicationListener。
    • 推断并设置main方法的定义类。

    2) SpringApplication实例初始化完成并且完成设置后,就开始执行run方法的逻辑了,方法执行伊始,首先遍历执行所有通过SpringFactoriesLoader可以查找到并加载的SpringApplicationRunListener。调用它们的started()方法,告诉这些SpringApplicationRunListener,“嘿,SpringBoot应用要开始执行咯!”。

    3) 创建并配置当前Spring Boot应用将要使用的Environment(包括配置要使用的PropertySource以及Profile)。

    4) 遍历调用所有SpringApplicationRunListener的environmentPrepared()的方法,告诉他们:“当前SpringBoot应用使用的Environment准备好了咯!”。

    5) 如果SpringApplication的showBanner属性被设置为true,则打印banner。

    6) 根据用户是否明确设置了applicationContextClass类型以及初始化阶段的推断结果,决定该为当前SpringBoot应用创建什么类型的ApplicationContext并创建完成,然后根据条件决定是否添加ShutdownHook,决定是否使用自定义的BeanNameGenerator,决定是否使用自定义的ResourceLoader,当然,最重要的,将之前准备好的Environment设置给创建好的ApplicationContext使用。

    7) ApplicationContext创建好之后,SpringApplication会再次借助Spring-FactoriesLoader,查找并加载classpath中所有可用的ApplicationContext-Initializer,然后遍历调用这些ApplicationContextInitializer的initialize(applicationContext)方法来对已经创建好的ApplicationContext进行进一步的处理。

    8) 遍历调用所有SpringApplicationRunListener的contextPrepared()方法。激发事件

    9) 最核心的一步,将之前通过@EnableAutoConfiguration获取的所有配置以及其他形式的IoC容器配置加载到已经准备完毕的ApplicationContext。

    10) 遍历调用所有SpringApplicationRunListener的contextLoaded()方法。

    11) 调用ApplicationContext的refresh()方法,完成IoC容器可用的最后一道工序。

    12) 查找当前ApplicationContext中是否注册有CommandLineRunner,如果有,则遍历执行它们。

    13) 正常情况下,遍历执行SpringApplicationRunListener的finished()方法、(如果整个过程出现异常,则依然调用所有SpringApplicationRunListener的finished()方法,只不过这种情况下会将异常信息一并传入处理)

    去除事件通知点后,整个流程如下:


    ConfigurationClassBeanDefinitionReader阅读器会从以下四个方面提取bean定义对象.

    d.1. 配置类自身,如果它被其它配置类导入了。

         d.2. 配置类中被@Bean注解的方法。

         d.3.配置类@ImportResource导入的xml配置文件。

         d.4.配置类@Import导入的ImportBeanDefinitionRegistrar。

    @ConfigurationProperties实现自动配置,类似@PropertySource("classpath:jdbc.properties")

    SpringFactoriesLoader属于Spring框架专属的一种扩展方案(其功能和使用方式类似于Java的SPI方案:java.util.ServiceLoader),它的主要功能就是从指定的配置文件META-INF/spring.factories中加载配置,spring.factories是一个非常经典的java properties文件,内容格式是Key=Value形式,只不过这Key以及Value都非常特殊,为Java类的完整类名(Fully qualified name)

    springboot初始化过程中主要是扫描两个spring.factoies文件,其中定义的key-value中的类,是整个启动过程中要用到的。一个是spring-boot-2.0.3.RELEASE中的,一个是spring-boot-autoconfigure包中的。这两个jar包中的文件定义整个启动流程中要执行的所有默认配置好的类。

     SpringFactories源码如下

    public abstract class SpringFactoriesLoader {
    
        private static final Log logger = LogFactory.getLog(SpringFactoriesLoader.class);
    
        public static final String FACTORIES_RESOURCE_LOCATION = "META-INF/spring.factories";
    
        public static <T> List<T> loadFactories(Class<T> factoryClass, ClassLoader classLoader){
            ...
        }
    
        public static List<String> loadFactoryNames(Class<?> factoryClass, ClassLoader classLoader) {
            ...
        }
        // ...
    }

    对于@EnableAutoConfiguraion来说,SpringFactoriesLoader的用途和其本意稍微不同,它本意是为了提供SPI扩展,而在@EnableAutoConfiguration这个场景下,它更多的是提供了一种配置查找的功能的支持. 

    总结来说,@EnableAutoConfiguration能实现自动配置的原理就是:SpringFactoriesLoader从classpath中搜寻所有META-INF/spring.fatories文件,并将其中Key[org.springframework.boot.autoconfigure.EnableAutoConfiguration]对应的Value配置项通过反射的方式实例化为对应的标注了@Configuration的JavaConfig形式的IoC容器配置类,然后汇总到当前使用的IoC容器中。


    SpringApplicationRunListener

    它其实是用来在整个启动流程中接收不同执行点事件通知的监听者。源码如下:

    public interface SpringApplicationRunListener {
        void starting();
        void environmentPrepared(ConfigurableEnvironment environment);
        void contextPrepared(ConfigurableApplicationContext context);
        void contextLoaded(ConfigurableApplicationContext context);
        void finished(ConfigurableApplicationContext context, Throwable exception);
    }

    ApplicationListener

    ApplicationListener不是新东西,它属于Spring框架对Java中实现的监听者模式的一种框架实现

     Spring内部实现类包括:

    org.springframework.boot.ClearCachesApplicationListener,
    org.springframework.boot.builder.ParentContextCloserApplicationListener,
    org.springframework.boot.context.FileEncodingApplicationListener,
    org.springframework.boot.context.config.AnsiOutputApplicationListener,
    org.springframework.boot.context.config.ConfigFileApplicationListener,
    org.springframework.boot.context.config.DelegatingApplicationListener,
    org.springframework.boot.liquibase.LiquibaseServiceLocatorApplicationListener,
    org.springframework.boot.logging.ClasspathLoggingApplicationListener,
    org.springframework.boot.logging.LoggingApplicationListener
    

      

    ApplicationContextInitializer

     这货也是Spring框架原有的东西,这个类的主要作用就是在ConfigurableApplicationContext类型(或者子类型)的ApplicationContext做refresh之前,允许我们对ConfiurableApplicationContext的实例做进一步的设置和处理。

    该类定义如下;

    public interface ApplicationContextInitializer<C extends ConfigurableApplicationContext> {
        void initialize(C applicationContext);
    }

    Spring boot 下默认实现包括

    org.springframework.boot.context.ConfigurationWarningsApplicationContextInitializer,
    org.springframework.boot.context.ContextIdApplicationContextInitializer,
    org.springframework.boot.context.config.DelegatingApplicationContextInitializer,
    org.springframework.boot.context.embedded.ServerPortInfoApplicationContextInitializer
    

      

    CommandLineRunner

    CommandLineRunner并不是Spring框架原有的概念,它属于SpringBoot应用特定的回调扩展接口:

    定义如下;
    public interface CommandLineRunner {
    
        void run(String... args) throws Exception;
    }

    关于这货,我们需要关注的点有两个:

    1. 所有CommandLineRunner的执行时间点是在SpringBoot应用的Application完全初始化工作之后(这里我们可以认为是SpringBoot应用启动类main方法执行完成之前的最后一步)。
    2. 当前SpringBoot应用的ApplicationContext中的所有CommandLinerRunner都会被加载执行(无论是手动注册还是被自动扫描注册到IoC容器中)。
  • 相关阅读:
    自制编译器 青木峰郎 笔记 Ch8 AST生成
    自制编译器 青木峰郎 笔记 Ch7 JavaCC的action和AST
    POJ 3349-Snowflake Snow Snowflakes-字符串哈希
    POJ 2112-Optimal Milking-二分答案+二分图匹配
    POJ 1258 -Agri-Net- 最小生成树
    POJ 1125-Stockbroker Grapevine-最短路
    POJ 3621-Sightseeing Cows-最优比率环|SPFA+二分
    POJ2976-Dropping tests-01分数规划
    POJ 3020 -Antenna Placement-二分图匹配
    POJ 3041-Asteroids-二分图匹配
  • 原文地址:https://www.cnblogs.com/snow-man/p/10795901.html
Copyright © 2020-2023  润新知