Spring系列梳理二:SpringApplication.run()之createApplicationContext

ApplicationContext

整体流程如下
在这里插入图片描述

源码走读:

创建ApplicationContext

源码如下:

protected ConfigurableApplicationContext createApplicationContext() {
   Class<?> contextClass = this.applicationContextClass;
   if (contextClass == null) {
      try {
         switch (this.webApplicationType) {
         case SERVLET:
            contextClass = Class.forName(DEFAULT_SERVLET_WEB_CONTEXT_CLASS);
            break;
         case REACTIVE:
            contextClass = Class.forName(DEFAULT_REACTIVE_WEB_CONTEXT_CLASS);
            break;
         default:
            contextClass = Class.forName(DEFAULT_CONTEXT_CLASS);
         }
      }
      catch (ClassNotFoundException ex) {
         throw new IllegalStateException(
               "Unable create a default ApplicationContext, "
                     + "please specify an ApplicationContextClass",
               ex);
      }
   }
   return (ConfigurableApplicationContext) BeanUtils.instantiateClass(contextClass);
}

根据webApplicationType创建ContextClass

如果是SERVLET,则实例化一个org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext对象

如果是REACTIVE,则实例化一个org.springframework.boot.web.reactive.context.AnnotationConfigReactiveWebServerApplicationContext

其他webApplicationType的话就按照默认的走,默认实例化一个org.springframework.context.annotation.AnnotationConfigApplicationContext

webApplicationType的由来

在实例化webApplicationType的时候,会初始化webApplicationType。关键代码如下:

this.webApplicationType = WebApplicationType.deduceFromClasspath();

如下是设置webApplicationType的代码

static WebApplicationType deduceFromClasspath() {
   if (ClassUtils.isPresent(WEBFLUX_INDICATOR_CLASS, null)
         && !ClassUtils.isPresent(WEBMVC_INDICATOR_CLASS, null)
         && !ClassUtils.isPresent(JERSEY_INDICATOR_CLASS, null)) {
      return WebApplicationType.REACTIVE;
   }
   for (String className : SERVLET_INDICATOR_CLASSES) {
      if (!ClassUtils.isPresent(className, null)) {
         return WebApplicationType.NONE;
      }
   }
   return WebApplicationType.SERVLET;
}

可以看到,当ClassPath下面有org.springframework.web.reactive.DispatcherHandler并且不包含org.springframework.web.servlet.DispatcherServlet

org.glassfish.jersey.servlet.ServletContainer的时候。则认为是REACTIVE的应用。会在后面的流程中,启动reactive web服务器。

REACTIVE应用的场景下,如果classPath下面包含javax.servlet.Servletorg.springframework.web.context.ConfigurableWebApplicationContext的时候,则认为不是web应用,不会启动内嵌的webServer

以上两种情况,即不是REACTIVE也不是非WEB应用,则认为是SERVLET应用,会启动内嵌的servlet web服务器

本案例以Servlet应用为例,分析

AnnotationConfigServletWebServerApplicationContext

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LuL0h3Oo-1631866765267)(D:%5C2020H2%5C8.vueblog%5Cnote-book-vuepress-demo%5Cdocs%5CJava%5CSpring%5CAnnotationConfigServletWebServerApplicationContext.assets%5Cimage-20210914203740188.png)]

接口:

AnnotationConfigRegistry

定义了一个annotationConfigApplicationContext的通用方法,一个是register一个是scan

register顾名思义就是注册bean到BeanFactory中。

而scan就是扫描指定basepackages下的所有bean

(D:%5C2020H2%5C8.vueblog%5Cnote-book-vuepress-demo%5Cdocs%5CJava%5CSpring%5CAnnotationConfigServletWebServerApplicationContext.assets%5Cimage-20210916170326957.png)]

可以看到AnnotationConfigRegistry的实现类有包含了servletreact以及非web的ApplicationContext

继承父类:

AnnotationConfigServletWebServerApplicationContext->ServletWebServerApplicationContext->GenericWebApplicationContext->GenericApplicationContext->AbstractApplicationContext->DefaultResourceLoader

顺便溜一句

Java实例化一个对象的时候,父类和子类的初始化顺序。

父类的静态成员变量和静态代码块

子类的静态成员变量和静态代码块

父类中普通成员变量和代码块,父类的构造函数

子类中普通成员变量和代码块,子类的构造函数

巧记:

1、静态成员变量和静态代码,是类初始化的时候优先初始化的。

2、new一个对象的时候,有个前提就是类初始化好了,才会实例化一个对象。

所以先静态后普通,先爸爸后儿子。

所以我们先看下父类的各种重要属性:

抽象类AbstractApplicationContext

(D:%5C2020H2%5C8.vueblog%5Cnote-book-vuepress-demo%5Cdocs%5CJava%5CSpring%5CAnnotationConfigServletWebServerApplicationContext.assets%5Cimage-20210916193700124.png)]

AbstactApplicationContext定义类一个ApplicationContext的共有的属性和方法,看一下关键属性。

beanFactoryPostProcessors

refresh阶段,需要调用BeanFactoryPostProcessor的postProcessBeanFactory()方法,去对BeanFactory进行处理。

beanFactoryPostProcessors就是存储后处理器的列表。

一般在初始化器ApplicationContextInitializer或者监听器ApplicationListener中添加。以为上面说了,这个BeanFactoryPostProcessorApplicationContextreresh的时候执行的。那也就是在refresh之前要进行添加好。在refresh之前,那也就是初始化器,以及监听器监听到在在refresh之前的事件。

如:ConfigurationWarningsApplicationContextInitializer和SharedMetadataReaderFactoryContextInitializer是在初始化阶段添加ConfigurationWarningsPostProcessorCachingMetadataReaderFactoryPostProcessor这两个后处理器的。

比如ConfigFileApplicationListener就是在ApplicationPreparedEvent阶段,添加了PropertySourceOrderingPostProcessor后处理器到beanFactoryPostProcessors中。

lifecycleProcessor

ApplicationContext各个阶段的生命周期回调。原理是AbstractApplicationContext实现了ConfigurableApplicationContext接口里面的生命周期相关函数。

比如在refresh完成后,根据配置执行registerShutdownHook,也就是注册一个JVM shutdown的hook。在JVM shutdown的时候进行回调处理。就调用的是lifecycleProcessor的处理能力。

父类GenericApplicationContext

(D:%5C2020H2%5C8.vueblog%5Cnote-book-vuepress-demo%5Cdocs%5CJava%5CSpring%5CAnnotationConfigServletWebServerApplicationContext.assets%5Cimage-20210917093304485.png)]

GenericApplicationContext实现了BeanDefinitionRegistry接口,继承AbstractApplicationContext

实现了BeanDefinitionRegistry,说明其具备对BeanDefinition的增删改查的能力。

GenericApplicationContext典型用法是通过BeanDefinitionRegistry接口的实现,去注册``BeanDefinition。之后通过调用refresh()`去初始化这些Bean。

相比于其他ApplicationContextGenericApplicationContext在创建好以后beanFactory就已经初始化完成了。refresh只能调用一次。

而其他的ApplicationContext,在每次refresh的时候会其创建一个内部的beanFactory。

属性
beanFactory

BeanFactory是属于GenericApplicationContext的属性。在GenericApplicationContext的无参构造方法有这么一条,说明beanFactory是一个DefaultListableBeanFactory实例

BeanFactory顾名思义,是Bean的工厂,先注册Bean,后访问Bean。

public GenericApplicationContext() {
   this.beanFactory = new DefaultListableBeanFactory();
}

AnnotationConfigServletWebServerApplicationContext

看下构造方法:

public AnnotationConfigServletWebServerApplicationContext() {
   this.reader = new AnnotatedBeanDefinitionReader(this);
   this.scanner = new ClassPathBeanDefinitionScanner(this);
}
AnnotatedBeanDefinitionReader

这个Reader是用于读取class文件。在AnnotatedBeanDefinitionReader对象实例化的过程中,会注册一些BeanPostProcessorBeanFactoryPostProcessor。这些处理器会在后面对应的流程中用到。

源码如下:是AnnotatedBeanDefinitionReader的构造方法。

public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry, Environment environment) {
   Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
   Assert.notNull(environment, "Environment must not be null");
   this.registry = registry;
   this.conditionEvaluator = new ConditionEvaluator(registry, environment, null);
   AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
}

重点看下最后一句AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);

public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(
      BeanDefinitionRegistry registry, @Nullable Object source) {

   DefaultListableBeanFactory beanFactory = unwrapDefaultListableBeanFactory(registry);
   if (beanFactory != null) {
      if (!(beanFactory.getDependencyComparator() instanceof AnnotationAwareOrderComparator)) {
         beanFactory.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE);
      }
      if (!(beanFactory.getAutowireCandidateResolver() instanceof ContextAnnotationAutowireCandidateResolver)) {
         beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());
      }
   }

   Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet<>(8);

   if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {
      RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
      def.setSource(source);
      beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));
   }

   if (!registry.containsBeanDefinition(AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
      RootBeanDefinition def = new RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class);
      def.setSource(source);
      beanDefs.add(registerPostProcessor(registry, def, AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
   }

   if (!registry.containsBeanDefinition(REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
      RootBeanDefinition def = new RootBeanDefinition(RequiredAnnotationBeanPostProcessor.class);
      def.setSource(source);
      beanDefs.add(registerPostProcessor(registry, def, REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
   }

   // Check for JSR-250 support, and if present add the CommonAnnotationBeanPostProcessor.
   if (jsr250Present && !registry.containsBeanDefinition(COMMON_ANNOTATION_PROCESSOR_BEAN_NAME)) {
      RootBeanDefinition def = new RootBeanDefinition(CommonAnnotationBeanPostProcessor.class);
      def.setSource(source);
      beanDefs.add(registerPostProcessor(registry, def, COMMON_ANNOTATION_PROCESSOR_BEAN_NAME));
   }

   // Check for JPA support, and if present add the PersistenceAnnotationBeanPostProcessor.
   if (jpaPresent && !registry.containsBeanDefinition(PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME)) {
      RootBeanDefinition def = new RootBeanDefinition();
      try {
         def.setBeanClass(ClassUtils.forName(PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME,
               AnnotationConfigUtils.class.getClassLoader()));
      }
      catch (ClassNotFoundException ex) {
         throw new IllegalStateException(
               "Cannot load optional framework class: " + PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME, ex);
      }
      def.setSource(source);
      beanDefs.add(registerPostProcessor(registry, def, PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME));
   }

   if (!registry.containsBeanDefinition(EVENT_LISTENER_PROCESSOR_BEAN_NAME)) {
      RootBeanDefinition def = new RootBeanDefinition(EventListenerMethodProcessor.class);
      def.setSource(source);
      beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_PROCESSOR_BEAN_NAME));
   }

   if (!registry.containsBeanDefinition(EVENT_LISTENER_FACTORY_BEAN_NAME)) {
      RootBeanDefinition def = new RootBeanDefinition(DefaultEventListenerFactory.class);
      def.setSource(source);
      beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_FACTORY_BEAN_NAME));
   }

   return beanDefs;
}

可以看到在BeanFactory中注册一些spring内部处理的Bean。注意:BeanFactory中有存储Bean定义的beanDefinitionMap,也有beanPostProcessors,本环节只是讲如下一些内部的bean注册到beanMap中,这些bean如下所示:

解析@ConfigurationCONFIGURATION_BEAN_NAME_GENERATOR(org.springframework.context.annotation.internalConfigurationBeanNameGenerator),也就是ConfigurationClassPostProcessor类。

解析@AutowiredAUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME(org.springframework.context.annotation.internalAutowiredAnnotationProcessor),也就是AutowiredAnnotationBeanPostProcessor

解析@RequiredREQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME(org.springframework.context.annotation.internalRequiredAnnotationProcessor),也就是RequiredAnnotationBeanPostProcessor

解析JSR-250规范注解的COMMON_ANNOTATION_PROCESSOR_BEAN_NAME(org.springframework.context.annotation.internalCommonAnnotationProcessor),也就是CommonAnnotationBeanPostProcessor

以及后面注册的一些ListenerFactory

总结一下,这些Bean,要么是BeanPostProcessor实现类,要么就是ApplicationContextAware

这些Bean注册后,在refresh后面的流程中都会用到,比如BeanPostPorcessor会在registerBeanPostProcessors中用到。

ClassPathBeanDefinitionScanner

ClassPathBeanDefinitionScanner是一个扫描指定类路径中注解Bean定义的扫描器,在它初始化的时候,会初始化一些需要被扫描的注解,初始化用于加载包下的资源的

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值