• springboot启动过程(1)-初始化


    1   springboot启动时,只需要调用一个类前面加了@SpringBootApplication的main函数,执行SpringApplication.run(DemoApplication.class, args)即可,这里初始化了一个SpringApplication实例,然后调用run启动springboot。run方法中,调用了initialize,如下

    @SuppressWarnings({ "unchecked", "rawtypes" })
    private void initialize(Object[] sources) {

          //把传入的source设置到SpringApplication的变量中 
      if (sources != null && sources.length > 0) {
        this.sources.addAll(Arrays.asList(sources));
      }

         // 如果是web程序,设置web环境。web程序必须让类加载器存在servlet 和 ConfigurableWebApplicationContext
      this.webEnvironment = deduceWebEnvironment();

         //找到ApplicationContextInitializer类实例化为成员变量,这个过程是找到所有的初始化器。
      setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
      //把ApplicationListener实例化为变量,就是找到所有的事件监听器。

          setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));

          //找到入口类,即放置main函数的类。

      this.mainApplicationClass = deduceMainApplicationClass();
    }

        (1)初始化context。 上面setInitializers 得到了ApplicationContextInitializer类型对象的集合,ApplicationContextInitializer是一个可以用来初始化各种ApplicationContex的接口,就一个initialize方法,上面初始化的时候用到了getSpringFactoriesInstances方法如下,

    private <T> Collection<? extends T> getSpringFactoriesInstances(Class<T> type,Class<?>[] parameterTypes, Object... args) {
      ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
      // Use names and ensure unique to protect against duplicates
      Set<String> names = new LinkedHashSet<String>(SpringFactoriesLoader.loadFactoryNames(type, classLoader));
      List<T> instances = createSpringFactoriesInstances(type, parameterTypes,classLoader, args, names);
      AnnotationAwareOrderComparator.sort(instances);
      return instances;
    }

          可以看到,方法用oadFactoryNames(type, classLoader));通过类型得到所有spring factories的名字,然后根据名字使用createSpringFactoriesInstances创造出实例对象,最后把创建好的对象排序并返回。springfactory是spring-boot-xxx(版本)包里面的META-INF/spring.factories如下 ,然后通过createSpringFactoriesInstances方法利用反射创造出这些实例,实例共四个都是ApplicationContextInitializer的实现类,作用也如下。

    # Application Context Initializers
    org.springframework.context.ApplicationContextInitializer=

    //为ApplicationContext添加一个能够检查配置,在错误配置时能够打印报错信息的BeanFactoryPostProcessor
    org.springframework.boot.context.ConfigurationWarningsApplicationContextInitializer,      

    //为ApplicationContext设置id
    org.springframework.boot.context.ContextIdApplicationContextInitializer,

    //从ApplicationContext的环境配置中,读取Initializer并使用
    org.springframework.boot.context.config.DelegatingApplicationContextInitializer,

    //为ApplicationContext设置一个环境变量,方便使用服务器正在监听的端口号。
    org.springframework.boot.context.embedded.ServerPortInfoApplicationContextInitializer

        (2)初始化监听器   上文中setListeners进行监听器初始化操作,跟初始化context一样,根据类型ApplicationListener.class从spring.factories里找到各种监听器,applicationListener就一个方法onApplicationEvent,用于监听各种事件。

    # Application Listeners
    org.springframework.context.ApplicationListener=
    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

           * applicationContext 事件机制    spring的事件机制基于观察者模式,与所有的事件机制都基本类似,他们都需要 事件源, 事件 和事件监听器 组成。只是此处的事件源是ApplicationContext。包括两个重要部分,

             ApplicationEvent: 容器事件,必须由 ApplicationContext发布。

        ApplicationListener: 监听器,可有容器中的任何监听器Bean担任。

            我们使用时可以定一个event继承ApplicationEvent,然后定一个listener继承ApplicationListener,实现onApplicationEvent方法,在方法里可以根据事件类型判断事件,进行响应处理。事件发布的时候,需要得到ApplicationContext,调用publishEvent(event)进行发布即可。spring也内置了几个事件。

       (3)上文的最后,deduceMainApplicationClass方法中,通过获取当前方法调用栈,得到main函数的类,赋值给成员变量。

      

      

  • 相关阅读:
    redis中文API
    基于redis的分布式锁
    redis安装使用配置
    windows常用命令
    curl命令详解
    linux远程连接
    memcache在大型网站的应用策略
    缓存使用的一些注意事项
    记录memcache分布式策略及算法
    U盘安装Centos7.0图解
  • 原文地址:https://www.cnblogs.com/lkdirk/p/7127097.html
Copyright © 2020-2023  润新知