spring boot学习笔记

441 阅读4分钟

springapplication 启动过程

  1. springapplication.initilizer初始化

    1. 判断是否web环境
    2. getSpringFactoriesInstances 分别获取ApplicationContextInitializer, ApplicationListener的实现
      • 2.1 loadFactoryNames 加载META-INF/spring.factories中配置的ApplicationContextInitializer, ApplicationListener的实现
      • 2.2 createSpringFactoriesInstances 通过反射,获取上一步中获取到的实现类的实例
    3. 获取main方法所在类型
  2. springapplication.run

    1. getRunListeners() 同样通过getSpringFactoriesInstances查找配置的SpringApplicationRunListener对应的实现

    2. listeners.starting() 发送start,准备启动的通知

    3. ApplicationArguments applicationArguments = new DefaultApplicationArguments(args); 加载命令行参数

    4. prepareEnvironment() 准备环境

      • 4.1 getOrCreateEnvironment() 获取环境加载实例,根据是否为web而创建不同的环境准备
      • 4.2 configureEnvironment() 配置环境(配置sources追加,设置activeProfiles)
      • 4.3 listeners.environmentPrepared() 发送环境准备通知
    5. printBanner() 打印banner

    6. createApplicationContext() 创建applicationcontext

      • a. 如果是web环境,加载并实例化AnnotationConfigEmbeddedWebApplicationContext,其在实例化的过程中, 会在相继的父类中完成以下配置。 GenericApplicationContext: beanFacotry = new DefaultListableBeanFactory() AbstractApplicationContext: resourcePatternResolver = new PathMatchingResourcePatternResolver(this) self: new AnnotatedBeanDefinitionReader(this); new ClassPathBeanDefinitionScanner(this);

      • b. 否则加载并实例化AnnotationConfigApplicationContext 同上

    7. new FailureAnalyzer(context) 加载META-INF/spring.factories中对应的FailureAnalyzer的类,这里有一个NoSuchBeanDefinitionFailureAnalyzer,当设置beanFactory时, 会注册第一个bean(autoConfigurationReport -->ConditionEvaluationReport)到DefaultListableBeanFactory与DefaultSingletonBeanRegistry当中, 即放在这两个类各自的map中.在下一步中initialize中,会有一个AutoConfigurationReportLoggingInitializer方法会调用到,并实例化第一个bean

    8. prepareContext() 准备context

      • 8.1 设置环境
      • 8.2 注册beanName生成类, 设置资源加载类, 设置classloader
      • 8.3 调用所有ApplicationContextInitializer实现类的initialize()
      • 8.4 发送listeners.contextPrepared(context)通知
      • 8.5 注册单例的参数实例,banner打印实例
      • 8.6 创建beandefinitionLoader实例(创建各种bean的加载类: xml, annotation, classpathScanner)
      • 8.7 加载注册启动类为beandefinition
      • 8.8 listeners.contextLoaded(context)发送context加载通知
    9. refreshContext() 刷新context

      • 9.1 prepareRefresh() 刷新准备 a.初始化属性信息 b.验证环境必要属性是否存在

      • 9.2 obtainFreshBeanFactory() 刷新获取beanfactory

      • 9.3 prepareBeanFactory() 设置一堆beanfactory的属性,相关引用的类等.包括如下 //classloader beanFactory.setBeanClassLoader(this.getClassLoader()); //expression解析器 beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader())); //资源编辑注册器 beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, this.getEnvironment())); //aware后置处理器 (这里就是设置各种aware环境的属性注入的地方) beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this)); //listeners的后置处理器 (context添加监听器bean) //这里的探测器实现了两个接口 DestructionAwareBeanPostProcessor, MergedBeanDefinitionPostProcessor,待研究 beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));

        注册环境相关的bean

      • 9.4 postProcessBeanFactory() //用于设置web servlet相关配置 EmbeddedWebApplicationContext: beanFacotry.addBeanPostProcessor(new WebApplicationContextServletContextAwareProcessor(this)); //查看是否有配置scannPackages或者annotatedClasses, 如果有加载注册成bean

      • 9.5 invokeBeanFactoryPostProcessors

        1. 首先查找BeanDefinitionRegistryPostProcessor的内部实现类,然后调用其实postProcessBeanDefinitionRegistry方法,前进一些检查告警,属性替换等;这里默认只有一个。

        2. 先执行实现了PriorityOrdered接口的(invokeBeanDefinitionRegistryPostProcessors(priorityOrderedPostProcessors, registry)), 这里只有 默认的ConfigurationClassPostProcessor,该类实现@Configuration的解析,内部通过ConfigurationClassParser来完成。具体如下: 处理嵌套的MemberClass 处理@PropertySource标签,用来解析属性文件并设置到Environment中。 处理@ComponentScan标签,扫描package下的所有Class并进行迭代解析。 处理@Import标签。 处理@ImportResource标签。 处理@Bean标签。 处理所有继承的Interface上的@Bean标签。 处理SuperClass。 处理标签中的DeferredImport。

        ps: processConfigurationClass 方法会按上述解析封装成ConfigClass类,里面是加注了@Configuration类的各种属性信息 loadBeanDefinitions(configClasses) 加载解析@Configuration中的注解, loadBeanDefinitionsForBeanMethod中会把@Bean修饰的方法注册bean

        1. 然后执行实现了Ordered接口的(invokeBeanDefinitionRegistryPostProcessors(orderedPostProcessors, registry)),这里如果有自定义的实现(因为上一步解析已经把自定义的bean注册过了) 且实现Ordered接口,那么将会调用执行其postProcessBeanDefinitionRegistry方法。

        2. 再然后就是处理普通的实现了,会过滤掉上面已经执行过的。一般这个时候会执行我们自定义的。

        3. 因为BeanDefinitionRegistryPostProcessor继承于BeanFactoryPostProcessor,所以上述的执行过程中,会被分类(是否有实现BeanDefinitionRegistryPostProcessor)收集记录下来, 然后再分别调用其实postProcessBeanFactory的方法。这样基本处理完BeanDefinitionRegistryPostProcessor类型的实现。

        4. 然后就开始查找BeanFactoryPostProcessor接口的实现(会包含上面已经执行的,但分类时会过滤掉), 同样的按PriorityOrdered, Ordered,nonOrdered分为三类执行。 首先会执行优先级较高的(实现PriorityOrdered接口),这时会查找到PropertySourcesPlaceholderConfigurer类,进行资源属性的解析。 其次会执行实现了Ordered接口的 最后执行普通的,比如自定义的。 上面是根据bean名称进行查找beanDefinition的,但如果这里的bean不是static方法修饰会报异常。(这里待深究)

        备注:beanFactory.getBean()方法会创建生成bean实例,同时会进行属性注入(这里待深究AbstractBeanFactory, AbstractAutowireCapableBeanFactory)

      • 9.6 registerBeanPostProcessors() 生成并注册BeatPostProcessor的实现,同样有优先级

      • 9.7 initMessageSource(), initApplicationEventMulticaster() 初始化消息资源与事件发布器

      • 9.8 onRefresh() 会调用EmbeddedWebApplicationContext,然后创建内嵌servlet容器 这里会根据条件查找到tomcat或者jetty等容器,并进行初始化等操作

      • 9.9 registerListeners() 执行监听器

      • 9.10 finishBeanFactoryInitialization() 实现化所有bean (待深究)

      • 9.11 finishRefresh() 完成刷新 AbstractApplicationContext 会先初始化一个默认的生命周期处理器,然后调用其实刷新方法。 然后发布context刷新事件. EmbeddedWebApplicationContext 会启动内嵌的servlet容器, 同时发布servlet容器初始化事件

    10. afterRefresh() 刷新之后 查找ApplicationRunner与CommandLineRunner实现类,然后调用其run方法

    11. listeners.finished()发送启动完成通知

ps: 这里有两个比较重要的方法待学习, 里面完成了bean的实例化,依赖注入及后置处理等相关操作. beanFactory.getBean beanFactory.getBeanNamesForType