spring boot 源码解析6-SpringApplication#run第6步

前言

之前我们分析了SpringApplication#run方法的前5步.接下来我们分析第6步.创建ApplicationContext.前5步如下:

  1. 初始化StopWatch,调用其start方法开始计时.
  2. 设置系统属性java.awt.headless,这里设置为true,表示运行在服务器端,在没有显示器和鼠标键盘的模式下工作,模拟输入输出设备功能
  3. 调用SpringApplicationRunListeners#starting
  4. 创建一个DefaultApplicationArguments对象,调用prepareEnvironment方法进行 Environment的设置
  5. 打印banner

分析

  1. 第6步是通过调用SpringApplication#createApplicationContext方法完成的.代码如下:

    protected ConfigurableApplicationContext createApplicationContext() {
        Class<?> contextClass = this.applicationContextClass;
        if (contextClass == null) {
            try {
                contextClass = Class.forName(this.webEnvironment
                        ? DEFAULT_WEB_CONTEXT_CLASS : DEFAULT_CONTEXT_CLASS);
            }
            catch (ClassNotFoundException ex) {
                throw new IllegalStateException(
                        "Unable create a default ApplicationContext, "
                                + "please specify an ApplicationContextClass",
                        ex);
            }
        }
        return (ConfigurableApplicationContext) BeanUtils.instantiate(contextClass);
    }

    很简单.通过判断当前是否是web环境决定创建什么类,如果是web程序,那么创建org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext的实例,否则创建org.springframework.context.annotation.AnnotationConfigApplicationContext的实例,这些都是定义在SpringApplication类的静态属性中.

    由于我们一般都是在web环境中,因此会初始化AnnotationConfigEmbeddedWebApplicationContext.

  2. AnnotationConfigEmbeddedWebApplicationContext 类的继承关系如下:

    《spring boot 源码解析6-SpringApplication#run第6步》

    通过类初始化顺序可知.首先会初始化DefaultResourceLoader.其构造器如下:

    public DefaultResourceLoader() {
        this.classLoader = ClassUtils.getDefaultClassLoader();
    }

    只是获得了一个类加载器.

    接下来初始化AbstractApplicationContext.其构造器如下:

    public AbstractApplicationContext() {
        this.resourcePatternResolver = getResourcePatternResolver();
    }

    调用了getResourcePatternResolver方法获得ResourcePatternResolver.代码如下:

    protected ResourcePatternResolver getResourcePatternResolver() {
        return new PathMatchingResourcePatternResolver(this);
    }

    将自己对于当前场景来说是AnnotationConfigEmbeddedWebApplicationContext传入了进去.构造器如下:

    public PathMatchingResourcePatternResolver(ResourceLoader resourceLoader) {
        Assert.notNull(resourceLoader, "ResourceLoader must not be null");
        this.resourceLoader = resourceLoader;
    }

    接下来初始化GenericApplicationContext.其构造如下:

    public GenericApplicationContext() {
        this.beanFactory = new DefaultListableBeanFactory();
    }
  3. DefaultListableBeanFactory的初始化.DefaultListableBeanFactory的继承关系如下:

    《spring boot 源码解析6-SpringApplication#run第6步》
    还是通过继承关系可知.会首先初始化SimpleAliasRegistry.其构造器为默认的无参构造器.没有做任何事.

    接下来初始化DefaultSingletonBeanRegistry,FactoryBeanRegistrySupport.同样是默认的无参构造器.没有做任何事.

    接下来初始化AbstractBeanFactory.其构造器如下:

    public AbstractBeanFactory() {
    }

    接着初始化AbstractAutowireCapableBeanFactory.构造器如下:

    public AbstractAutowireCapableBeanFactory() {
        super();
        ignoreDependencyInterface(BeanNameAware.class);
        ignoreDependencyInterface(BeanFactoryAware.class);
        ignoreDependencyInterface(BeanClassLoaderAware.class);
    }

    调用了ignoreDependencyInterface.将BeanNameAware,BeanFactoryAware,BeanClassLoaderAware 添加至ignoreDependencyInterface中.这是因为后续的context初始化时会对其进行处理.代码如下:

    public void ignoreDependencyInterface(Class<?> ifc) {
        this.ignoredDependencyInterfaces.add(ifc);
    }

    接着初始化DefaultListableBeanFactory.构造器如下:

    public DefaultListableBeanFactory() {
        super();
    }

    至此DefaultListableBeanFactory 也就初始化完毕了. 也就意味着GenericApplicationContext初始化完毕.

  4. 接下来 初始化GenericWebApplicationContext,EmbeddedWebApplicationContext.其构造器都是使用的默认的.没有做任何事.

  5. 最后,初始化AnnotationConfigEmbeddedWebApplicationContext.其构造器如下:

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

    初始化了AnnotatedBeanDefinitionReader,ClassPathBeanDefinitionScanner.

    AnnotatedBeanDefinitionReader构造器如下:

    public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry) {
        this(registry, getOrCreateEnvironment(registry));
    }

    首先调用getOrCreateEnvironment方法获得Environment.

    private static Environment getOrCreateEnvironment(BeanDefinitionRegistry registry) {
        Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
        if (registry instanceof EnvironmentCapable) {
            return ((EnvironmentCapable) registry).getEnvironment();
        }
        return new StandardEnvironment();
    }

    注意这里的registry为AnnotationConfigEmbeddedWebApplicationContext.因此会通过调用AbstractApplicationContext#getEnvironment 获得Environment.代码如下:

        public ConfigurableEnvironment getEnvironment() {
        if (this.environment == null) {
            this.environment = createEnvironment();
        }
        return this.environment;
    }

    由于此时environment 为null,因此调用GenericWebApplicationContext#createEnvironment进行创建.代码如下:

    protected ConfigurableEnvironment createEnvironment() {
        return new StandardServletEnvironment();
    }

    StandardServletEnvironment 继承关系如下:

    《spring boot 源码解析6-SpringApplication#run第6步》

    在AbstractEnvironment 初始化时,调用了customizePropertySources方法.

    public AbstractEnvironment() {
        customizePropertySources(this.propertySources);
        if (logger.isDebugEnabled()) {
            logger.debug("Initialized " + getClass().getSimpleName() + " with PropertySources " + this.propertySources);
        }
    }

    调用StandardServletEnvironment#customizePropertySources,代码如下:

    protected void customizePropertySources(MutablePropertySources propertySources) {
        propertySources.addLast(new StubPropertySource(SERVLET_CONFIG_PROPERTY_SOURCE_NAME));
        propertySources.addLast(new StubPropertySource(SERVLET_CONTEXT_PROPERTY_SOURCE_NAME));
        if (JndiLocatorDelegate.isDefaultJndiEnvironmentAvailable()) {
            propertySources.addLast(new JndiPropertySource(JNDI_PROPERTY_SOURCE_NAME));
        }
        super.customizePropertySources(propertySources);
    }
    1. 添加名为servletConfigInitParams的StubPropertySource
    2. 添加名为servletContextInitParams的StubPropertySource
    3. 如果是在jndi的环境中,则添加名为jndiProperties的JndiPropertySource.默认为false.

      JndiLocatorDelegate#isDefaultJndiEnvironmentAvailable代码如下:

      public static boolean isDefaultJndiEnvironmentAvailable() {
          if (shouldIgnoreDefaultJndiEnvironment) {
              return false;
          }
          try {
              new InitialContext().getEnvironment();
              return true;
          }
          catch (Throwable ex) {
              return false;
          }
      }
      1. 如果忽略jndi环境,则返回false.shouldIgnoreDefaultJndiEnvironment定义在JndiLocatorDelegate中,代码如下:

        private static final boolean shouldIgnoreDefaultJndiEnvironment =
        SpringProperties.getFlag(IGNORE_JNDI_PROPERTY_NAME);

        调用

        public static boolean getFlag(String key) {
            return Boolean.parseBoolean(getProperty(key));
        }

        调用

        public static String getProperty(String key) {
        String value = localProperties.getProperty(key);
        if (value == null) {
            try {
                value = System.getProperty(key);
            }
            catch (Throwable ex) {
                if (logger.isDebugEnabled()) {
                    logger.debug("Could not retrieve system property '" + key + "': " + ex);
                }
            }
        }
        return value;
        }
        1. 在SpringProperties中尝试加载spring.properties中的配置,由于默认清情况下,不存在,则会返回null.
        2. 从系统配置中读取spring.jndi.ignore的配置,由于我们没有配置,因此,还是返回null.

        因此,此处返回false.

      2. 尝试通过InitialContext#getEnvironment 判断是否存在jndi.如果抛出异常,则返回false,否则,返回true.

      默认情况下,此处会抛出异常,因此返回的是false

    4. 调用父类(StandardEnvironment)的customizePropertySources方法,代码如下:

      protected void customizePropertySources(MutablePropertySources propertySources) {
          propertySources.addLast(new MapPropertySource(SYSTEM_PROPERTIES_PROPERTY_SOURCE_NAME, getSystemProperties()));
          propertySources.addLast(new SystemEnvironmentPropertySource(SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME, getSystemEnvironment()));
      }

    因此 StandardEnvironment 也就持有了servletConfigInitParams,servletContextInitParams,systemProperties,systemEnvironment 4个PropertySource.

    之后调用AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry, Environment environment)构造器进行初始化.

    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);
    }

    做了2件事.

    1. 初始化了ConditionEvaluator,用于对@Conditional 注解的使用.
    2. 向AnnotationConfigEmbeddedWebApplicationContext进行注册.代码如下:

      public static void registerAnnotationConfigProcessors(BeanDefinitionRegistry registry) {
      registerAnnotationConfigProcessors(registry, null);
      }

      调用

      public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(
          BeanDefinitionRegistry registry, 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<BeanDefinitionHolder>(4);
      
      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;
      }

      做了10件事.

      1. 获得DefaultListableBeanFactory 代码如下:

        private static DefaultListableBeanFactory unwrapDefaultListableBeanFactory(BeanDefinitionRegistry registry) {
            if (registry instanceof DefaultListableBeanFactory) {
                return (DefaultListableBeanFactory) registry;
            }
            else if (registry instanceof GenericApplicationContext) {
                return ((GenericApplicationContext) registry).getDefaultListableBeanFactory();
            }
            else {
                return null;
            }
        }

        由于AnnotationConfigEmbeddedWebApplicationContext本身就是DefaultListableBeanFactory子类,因此这里将AnnotationConfigEmbeddedWebApplicationContext向上转型为DefaultListableBeanFactory后返回.

      2. 如果DefaultListableBeanFactory中的DependencyComparator不是AnnotationAwareOrderComparator实例的话,就设置DependencyComparator为AnnotationAwareOrderComparator.这里一般都会进行设置的.

      3. 如果DefaultListableBeanFactory中的AutowireCandidateResolver不是ContextAnnotationAutowireCandidateResolver实例的话,就实例化为ContextAnnotationAutowireCandidateResolver.

      4. 如果不包含org.springframework.context.annotation.internalConfigurationAnnotationProcessor 的bean的定义.就注册一个bean class为 ConfigurationClassPostProcessor
      5. 如果不包含org.springframework.context.annotation.internalAutowiredAnnotationProcessor 的 bean, 就注册一个 bean class 为 AutowiredAnnotationBeanPostProcessor
      6. 如果不包含org.springframework.context.annotation.internalRequiredAnnotationProcessor的 bean, 就注册一个 bean class 为 RequiredAnnotationBeanPostProcessor
      7. 如果当前类路径存在javax.annotation.Resource.并且registry中不包含org.springframework.context.annotation.internalCommonAnnotationProcessor的定义,那么就注册一个 bean class 为 CommonAnnotationBeanPostProcessor 的bean. 一般都会进行注册的.
      8. 如果当前类路径存在javax.persistence.EntityManagerFactory和 org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor 并且registry中不包含org.springframework.context.annotation.internalPersistenceAnnotationProcessor的 定义,那么就注册一个 class 为 org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor 的bean. 一般都会进行注册的.
      9. 如果registry 不包含org.springframework.context.event.internalEventListenerProcessor的 定义.就注册一个bean class 为 EventListenerMethodProcessor 的定义
      10. 如果registry 不包含org.springframework.context.event.internalEventListenerFactory的 定义. 就注册一个 class 为 DefaultEventListenerFactory 的定义
  6. 接下来初始化ClassPathBeanDefinitionScanner.其继承关系如下:

    《spring boot 源码解析6-SpringApplication#run第6步》
    还是同样的套路. ClassPathBeanDefinitionScanner的初始化会触发ClassPathScanningCandidateComponentProvider的初始化.其构造器如下:

    protected ClassPathScanningCandidateComponentProvider() {
    }

    然后初始化 ClassPathBeanDefinitionScanner.构造器如下:

    public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry) {
        this(registry, true);
    }

    注意这里传入的registry为AnnotationConfigEmbeddedWebApplicationContext.

    接着调用如下构造器:

    public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry, boolean useDefaultFilters) {
        this(registry, useDefaultFilters, getOrCreateEnvironment(registry));
    }

    这里调用getOrCreateEnvironment方法获得Environment.代码如下:

    private static Environment getOrCreateEnvironment(BeanDefinitionRegistry registry) {
        Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
        if (registry instanceof EnvironmentCapable) {
            return ((EnvironmentCapable) registry).getEnvironment();
        }
        return new StandardEnvironment();
    }

    由于在构造AnnotatedBeanDefinitionReader 已经初始化了Environment.因此这里就直接返回了StandardEnvironment.

    接下来调用如下构造器:

    public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry, boolean useDefaultFilters,
            Environment environment) {
    
        this(registry, useDefaultFilters, environment,
                (registry instanceof ResourceLoader ? (ResourceLoader) registry : null));
    }

    由于AnnotationConfigEmbeddedWebApplicationContext实现了ResourceLoader接口,因此这里将AnnotationConfigEmbeddedWebApplicationContext向上转型为ResourceLoader.

    进而调用如下构造器:

    public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry, boolean useDefaultFilters,
            Environment environment, ResourceLoader resourceLoader) {
    
        Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
        this.registry = registry;
    
        if (useDefaultFilters) {
            registerDefaultFilters();
        }
        setEnvironment(environment);
        setResourceLoader(resourceLoader);
    }

    3步:

    1. 如果使用默认过滤器的话,就调用registerDefaultFilters进行注册,一般都是为true的.因此为执行如下代码:

      protected void registerDefaultFilters() { // 1. 添加AnnotationTypeFilter-->Component this.includeFilters.add(new AnnotationTypeFilter(Component.class)); ClassLoader cl = ClassPathScanningCandidateComponentProvider.class.getClassLoader(); try { // 2. 添加AnnotationTypeFilter --> ManagedBean this.includeFilters.add(new AnnotationTypeFilter( ((Class<? extends Annotation>) ClassUtils.forName("javax.annotation.ManagedBean", cl)), false)); logger.debug("JSR-250 'javax.annotation.ManagedBean' found and supported for component scanning"); } catch (ClassNotFoundException ex) { // JSR-250 1.1 API (as included in Java EE 6) not available - simply skip. } try { // 3. 添加AnnotationTypeFilter --> javax.inject.Named this.includeFilters.add(new AnnotationTypeFilter( ((Class<? extends Annotation>) ClassUtils.forName("javax.inject.Named", cl)), false)); logger.debug("JSR-330 'javax.inject.Named' annotation found and supported for component scanning"); } catch (ClassNotFoundException ex) { // JSR-330 API not available - simply skip. } } 

      依旧3步:

      1. 添加AnnotationTypeFilter–>Component
      2. 添加AnnotationTypeFilter –> ManagedBean
      3. 添加AnnotationTypeFilter –> javax.inject.Named
    2. 设置Environment,就是简单的赋值,代码如下:

      public void setEnvironment(Environment environment) {
          Assert.notNull(environment, "Environment must not be null");
          this.environment = environment;
          this.conditionEvaluator = null;
      }
    3. 设置ResourceLoader.执行如下代码:

          public void setResourceLoader(ResourceLoader resourceLoader) {
      // 1. 设置ResourcePatternResolver
      this.resourcePatternResolver = ResourcePatternUtils.getResourcePatternResolver(resourceLoader);
      // 2. 实例化CachingMetadataReaderFactory
      this.metadataReaderFactory = new CachingMetadataReaderFactory(resourceLoader);
      }

      2 步:

      1. 设置ResourcePatternResolver.执行如下代码:

        public static ResourcePatternResolver getResourcePatternResolver(ResourceLoader resourceLoader) {
            if (resourceLoader instanceof ResourcePatternResolver) {
        return (ResourcePatternResolver) resourceLoader;
        }
        else if (resourceLoader != null) {
        return new PathMatchingResourcePatternResolver(resourceLoader);
        }
        else {
        return new PathMatchingResourcePatternResolver();
        }
        }

        由于当前环境下resourceLoader 是 ResourcePatternResolver的实例,因此直接返回.

      2. 实例化CachingMetadataReaderFactory.

    至此.SpringApplication#run 中的第6步–> 创建AnnotationConfigEmbeddedWebApplicationContext也就分析完了.

    原文作者:Spring Boot
    原文地址: https://blog.csdn.net/qq_26000415/article/details/78915181
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞