Spring Boot 启动源码解析结合Spring Bean生命周期分析

本文涉及的产品
全局流量管理 GTM,标准版 1个月
云解析 DNS,旗舰版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
简介: Spring Boot 启动源码解析结合Spring Bean生命周期分析

转载请注明出处:

目录

  1.源码流程图

  2.创建SpringApplication 应用,在构造函数中推断启动应用类型,并进行spring boot自动装配

  3.SpringApplication.run方法源码

    3.1 执行prepareEnvironment 方法,准备应用环境

      3.1.1 getOrCreateEnvironment 方法源码

      3.1.2 configureEnvironment() 方法获取配置环境  

    3.2.createApplicationContext方法

      3.2.1AnnotationConfigApplicationContext() 的构造方法

    3.3.prepareContext方法

    3.4 查看 refreshContext中refresh方法

      3.4.1 prepareRefresh()

      3.4.2 obtainFreshBeanFactory()

      3.4.3 prepareBeanFactory()

      3.4.4 invokeBeanFactoryPostProcessors()

      3.4.5 registerBeanPostProcessors()

      3.4.6 重点 finishBeanFactoryInitialization() 实现SpringBean生命周期过程

 

1.SpringBoot 源码执行流程图

 

2. 创建SpringApplication 应用,在构造函数中推断启动应用类型,并进行spring boot自动装配

 public static ConfigurableApplicationContext run(Class<?>[] primarySources, String[] args) {

       return (new SpringApplication(primarySources)).run(args);

   }

  查看 SpringApplication 构造函数

public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
        this.sources = new LinkedHashSet();
        // 获取banner打印模式
        this.bannerMode = Mode.CONSOLE;
        this.logStartupInfo = true;
        // 添加命令行系统属性
        this.addCommandLineProperties = true;
        this.addConversionService = true;
        this.headless = true;
        this.registerShutdownHook = true;
        this.additionalProfiles = Collections.emptySet();
        this.isCustomEnvironment = false;
         // 是否懒加载
        this.lazyInitialization = false;
        // 默认赋值 applicationContextFactory 工厂对象
        this.applicationContextFactory = ApplicationContextFactory.DEFAULT;
        this.applicationStartup = ApplicationStartup.DEFAULT;
        this.resourceLoader = resourceLoader;
        Assert.notNull(primarySources, "PrimarySources must not be null");
        this.primarySources = new LinkedHashSet(Arrays.asList(primarySources));
         // 根据类加载路径推断webApplicaitonType类型:SERVLET;REACTIVE
        this.webApplicationType = WebApplicationType.deduceFromClasspath();
        // 进行Spring的自动装配,主要用来SpringFactoriesLoader类进行装载工厂
        this.bootstrappers = new ArrayList(this.getSpringFactoriesInstances(Bootstrapper.class));
        this.setInitializers(this.getSpringFactoriesInstances(ApplicationContextInitializer.class));
         // 设置监听器
        this.setListeners(this.getSpringFactoriesInstances(ApplicationListener.class));
        this.mainApplicationClass = this.deduceMainApplicationClass();
    }

  getSpringFactoriesInstances 方法主要用来进行Spring的自动装配;用 SpringFactoriesLoader类 进行装载工厂,工厂资源位于 META-INF/spring.factories 文件中,这个文件可能在类路径的多个jar文件中。然后调用createSpringFactoriesInstances() 方法对工厂进行实例化并根据注解进行排序。

3.SpringApplication.run方法源码

  查看run方法源码

public ConfigurableApplicationContext run(String... args) {
        // 应用启动计时器
        StopWatch stopWatch = new StopWatch();
        stopWatch.start();
        DefaultBootstrapContext bootstrapContext = this.createBootstrapContext();
        // 初始化应用上下文
        ConfigurableApplicationContext context = null;
        this.configureHeadlessProperty();
        // 获取启动监听器
        SpringApplicationRunListeners listeners = this.getRunListeners(args);
        //监听器使用类似于生产-消费模式进行消息监听
        listeners.starting(bootstrapContext, this.mainApplicationClass);
        try {
            //构建应用参数
            ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
            //准备应用环境
            ConfigurableEnvironment environment = this.prepareEnvironment(listeners, bootstrapContext, applicationArguments);
            this.configureIgnoreBeanInfo(environment);
            //打印banner
            Banner printedBanner = this.printBanner(environment);
            //创建ApplicationContext
            context = this.createApplicationContext();
            context.setApplicationStartup(this.applicationStartup);
            //准备context
            this.prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner);
            //重点:刷新context:实现IOC容器启动的整个过程
            this.refreshContext(context);
            //后置工作
            this.afterRefresh(context, applicationArguments);
            stopWatch.stop();
            if (this.logStartupInfo) {
                (new StartupInfoLogger(this.mainApplicationClass)).logStarted(this.getApplicationLog(), stopWatch);
            }
            listeners.started(context);
            this.callRunners(context, applicationArguments);
        } catch (Throwable var10) {
            this.handleRunFailure(context, var10, listeners);
            throw new IllegalStateException(var10);
        }
        
    }

  获取启动监听器。实际上获取的是一个EventPublishingRunListener对象,这个类能通过一个SimpleApplicationEventMulticaster对象广播事件,用到了Executor多线程异步执行框架;

3.1 执行prepareEnvironment 方法,准备应用环境

  prepareEnvironment 方法源码

private ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners listeners, DefaultBootstrapContext bootstrapContext, ApplicationArguments applicationArguments) {
        // 根据前面推断的web环境类型创建推Environment对象
        ConfigurableEnvironment environment = this.getOrCreateEnvironment();
        // 进行环境配置
        this.configureEnvironment((ConfigurableEnvironment)environment, applicationArguments.getSourceArgs());
        ConfigurationPropertySources.attach((Environment)environment);
        listeners.environmentPrepared(bootstrapContext, (ConfigurableEnvironment)environment);
        DefaultPropertiesPropertySource.moveToEnd((ConfigurableEnvironment)environment);
        this.configureAdditionalProfiles((ConfigurableEnvironment)environment);
        this.bindToSpringApplication((ConfigurableEnvironment)environment);
        if (!this.isCustomEnvironment) {
            environment = (new EnvironmentConverter(this.getClassLoader())).convertEnvironmentIfNecessary((ConfigurableEnvironment)environment, this.deduceEnvironmentClass());
        }
        ConfigurationPropertySources.attach((Environment)environment);
        return (ConfigurableEnvironment)environment;
    }

  prepareEnvironment 方法主要用来准备应用环境,进行property配置文件解析,profile 环境解析以及获取系统属性和系统环境等;

3.1.1 getOrCreateEnvironment 方法源码

private ConfigurableEnvironment getOrCreateEnvironment() {
        if (this.environment != null) {
            return this.environment;
        } else {
            switch(this.webApplicationType) {
            case SERVLET:
                return new StandardServletEnvironment();
            case REACTIVE:
                return new StandardReactiveWebEnvironment();
            default:
                return new StandardEnvironment();
            }
        }
    }

   StandardEnvironment的构造器会先对属性源进行定制(将系统属性和系统环境添加到一个MutablePropertySources维护的list中)。这个对象的主要工作包括property分析、profile相关操作、获取系统属性和系统环境等

3.1.2 configureEnvironment() 方法获取配置环境

  configureEnvironment() 源码:

protected void configureEnvironment(ConfigurableEnvironment environment, String[] args) {
        if (this.addConversionService) {
            ConversionService conversionService = ApplicationConversionService.getSharedInstance();
            environment.setConversionService((ConfigurableConversionService)conversionService);
        }
        // 配置属性源
        this.configurePropertySources(environment, args);
        //获取激活的 profile
        this.configureProfiles(environment, args);
    }

  configureProfiles 方法通过AbstractEnvironment#getActiveProfiles() 解析 spring.profile.active 属性,添加到activeProfiles这个集合中。

3.2.createApplicationContext方法

createApplicationContext 方法源码
  protected ConfigurableApplicationContext createApplicationContext() {
        return this.applicationContextFactory.create(this.webApplicationType);
    }

  进入 applicationContextFactory.create 方法的类中,存在一个根据webApplicationType获取容器类型的变量方法如下:

@FunctionalInterface
public interface ApplicationContextFactory {
    // 根据webApplicationType返回指定的容器实例
    applicationContextFactoryApplicationContextFactory DEFAULT = (webApplicationType) -> {
        try {
            switch(webApplicationType) {
            case SERVLET:
                return new AnnotationConfigServletWebServerApplicationContext();
            case REACTIVE:
                return new AnnotationConfigReactiveWebServerApplicationContext();
            default:
                return new AnnotationConfigApplicationContext();
            }
        } catch (Exception var2) {
            throw new IllegalStateException("Unable create a default ApplicationContext instance, you may need a custom ApplicationContextFactory", var2);
        }
    };
      ConfigurableApplicationContext create(WebApplicationType webApplicationType);
}

  通过以上方式获取到具体的ApplicationContext实例,并通过构造函数进行实例化,查看构造函数的过程:

3.2.1AnnotationConfigApplicationContext() 的构造方法  

  构造方法源码如下:

public AnnotationConfigApplicationContext() {
        // 启动上面获取的容器类型实例
        StartupStep createAnnotatedBeanDefReader = this.getApplicationStartup().start("spring.context.annotated-bean-reader.create");
        // 构建AnnotatedBeanDefinitionReader对象
        this.reader = new AnnotatedBeanDefinitionReader(this);
        createAnnotatedBeanDefReader.end();
          // 构建 ClassPathBeanDefinitionScanner对象
        this.scanner = new ClassPathBeanDefinitionScanner(this);
    }

  AnnotationConfigApplicationContext的默认构造器会构造一个AnnotationBeanDefinitionReader对象和ClassPathBeanDefinitionScanner对象,在构造AnnotationBeanDefinitionReader对象的过程中会向bean factory添加注解处理器和事件监听处理器BeanDefinition,为后续的配置解析作准备。这样,就能通过JavaConfig 构建 BeanDefinition 并实现自动扫描。

  AnnotationConfigApplicationContext的父类GenericApplicationContext的默认构造器会构造一个DefaultListableBeanFactory 对象,这样应用上下文持有一个bean factory的引用,大部分应用只需与应用上下文提供的接口打交道就是因为它对bean factory进行了一层封装。至此,一个Spring容器已经构造出来了,但是目前这个容器还什么都没有,需要根据用户的配置文件进行配置才能按照用户逻辑进行工作。

 

3.3.prepareContext方法

  prepareContext 方法源码

private void prepareContext(DefaultBootstrapContext bootstrapContext, ConfigurableApplicationContext context, ConfigurableEnvironment environment, SpringApplicationRunListeners listeners, ApplicationArguments applicationArguments, Banner printedBanner) {
        // 使context持有应用环境的引用,同时将应用环境的引用赋给reader和scanner
        context.setEnvironment(environment);
        // 实现应用上下文的后置处理:主要是注册BeanNameGenerator类型的bean并设置应用上下文的资源加载器和类加载器
        this.postProcessApplicationContext(context);
        // 应用初始化器--添加监听器、logger、warnning、以及spring启动加解密等组件
        this.applyInitializers(context);
        listeners.contextPrepared(context);
        bootstrapContext.close(context);
        if (this.logStartupInfo) {
            this.logStartupInfo(context.getParent() == null);
            this.logStartupProfileInfo(context);
        }
        ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
        // 添加启动相关的bean
        beanFactory.registerSingleton("springApplicationArguments", applicationArguments);
        // 注册打印banner的bean
        if (printedBanner != null) {
            beanFactory.registerSingleton("springBootBanner", printedBanner);
        }
        // 注册可定义重写的bean
        if (beanFactory instanceof DefaultListableBeanFactory) {
            ((DefaultListableBeanFactory)beanFactory).setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
        }
        // 添加懒加载的bean工厂后置处理器
        if (this.lazyInitialization) {
            context.addBeanFactoryPostProcessor(new LazyInitializationBeanFactoryPostProcessor());
        }
        // Load the sources
        Set<Object> sources = this.getAllSources();
        Assert.notEmpty(sources, "Sources must not be empty");
        // 重点:将source bean装载到应用上下文
        this.load(context, sources.toArray(new Object[0]));
        // 日志配置
        listeners.contextLoaded(context);
    }

  该方法主要进行 context 添加初始化器,包括监听器、logger、warnning、以及spring启动加解密组件等等;并设置一些启动需要的 bean;

  通过 load 方法将所有的bean注册到 容器中;该方法实现的调用链如下:

SpringApplication.load(ApplicationContext context, Object[] sources)-------->
BeanDefinitionLoader.load()---->BeanDefinitionLoader.load(Object source)--->
BeanDefinitionLoader.load(Class<?> source)----->AnnotatedBeanDefinitionReader.register(Class<?>... componentClasses)--->
AnnotatedBeanDefinitionReader.registerBean(Class<?> beanClass)---->
AnnotatedBeanDefinitionReader.doRegisterBean --->
BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);

  需要关注 BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry) 这个操作;继续跟进这个方法的具体实现,会发现所有的 bean 注册都是保存在一个map中,比如DefaultListableBeanFactory 类中的registerBeanDefinition 方法是将bean保存到自定义的map集合中

private final Map<String, BeanDefinition> beanDefinitionMap;

 

3.4 refreshContext中refresh方法

  查看refreshContext 中 refresh 方法源码

public void refresh() throws BeansException, IllegalStateException {
  synchronized (this.startupShutdownMonitor) {
    // Prepare this context for refreshing.
    // 为应用上下文的刷新做准备--设置时间、记录刷新日志、初始化属性源中的占位符和验证必要的属性等
    prepareRefresh();
    // Tell the subclass to refresh the internal bean factory.
    // 使用CAS让子类刷新内部的bean factory
    ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
    // Prepare the bean factory for use in this context.
    // 准备在这个应用上下文中使用的bean factory
    prepareBeanFactory(beanFactory);
    try {
      // Allows post-processing of the bean factory in context subclasses.
      // bean factory 后置处理
      postProcessBeanFactory(beanFactory);
      // Invoke factory processors registered as beans in the context.
      // 调用应用上下文中作为bean注册的工厂处理器
      invokeBeanFactoryPostProcessors(beanFactory);
      // Register bean processors that intercept bean creation.
      // 注册拦截创建bean的bean处理器
      registerBeanPostProcessors(beanFactory);
      // Initialize message source for this context.
      // 初始化消息源
      initMessageSource();
      // Initialize event multicaster for this context.
      // 初始化事件广播
      initApplicationEventMulticaster();
      // Initialize other special beans in specific context subclasses.
      // 初始化特定上下文子类中的其它bean
      onRefresh();
      // Check for listener beans and register them.
      // 注册监听器bean
      registerListeners();
      // Instantiate all remaining (non-lazy-init) singletons.
      // 实例化所有的单例bean
      finishBeanFactoryInitialization(beanFactory);
      // Last step: publish corresponding event.
      // 发布相应的事件
      finishRefresh();
    }
    catch (BeansException ex) {
      if (logger.isWarnEnabled()) {
        logger.warn("Exception encountered during context initialization - " +
                            "cancelling refresh attempt: " + ex);
      }
      // Destroy already created singletons to avoid dangling resources.
      destroyBeans();
      // Reset 'active' flag.
      cancelRefresh(ex);
      // Propagate exception to caller.
      throw ex;
    }
    finally {
      // Reset common introspection caches in Spring's core, since we
      // might not ever need metadata for singleton beans anymore...
      resetCommonCaches();
    }
  }
}


3.4.1 prepareRefresh()

  AbstractApplicationContext#prepareRefresh() 源码:

protected void prepareRefresh() {
   //记录启动时间
   this.startupDate = System.currentTimeMillis();
   //标志位设置
   this.closed.set(false);
   this.active.set(true);
   //日志记录一下
   if (logger.isInfoEnabled()) {
       logger.info("Refreshing " + this);
   }
   // Initialize any placeholder property sources in the context environment
   // 初始化资源占位符
   initPropertySources();
   // Validate that all properties marked as required are resolvable
   // see ConfigurablePropertyResolver#setRequiredProperties
   // 验证所有必要的属性能通过getProperty()解析,不能则抛出异常
   getEnvironment().validateRequiredProperties();
   // Allow for the collection of early ApplicationEvents,
   // to be published once the multicaster is available...
   this.earlyApplicationEvents = new LinkedHashSet<ApplicationEvent>();
}

  创建environment并加载System.properties()及System.getenv()到environment中

 

3.4.2 obtainFreshBeanFactory()

  因为AbstractApplication没有引用bean factory,只定义了刷新bean factory相关的方法,刷新bean factory的具体实现在子类的GenericApplicationContext#refreshBeanFactory()中实现,具体代码和说明如下:

protected final void refreshBeanFactory() throws IllegalStateException {
   // 只支持刷新一次
   if (!this.refreshed.compareAndSet(false, true)) {
       throw new IllegalStateException("GenericApplicationContext does not support multiple refresh attempts: just call  'refresh' once");
   }
   // 设置序列号
   this.beanFactory.setSerializationId(getId());
}

  可以看到对bean factory的刷新实际上只是为其设置了一个序列号。

 

 

3.4.3 prepareBeanFactory()

   AbstractApplicationContext#prepareBeanFactory()。这个方法比较长,主要做的工作是对bean factory进行一些设置并添加一些辅助bean,具体代码和说明如下:

protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
   // Tell the internal bean factory to use the context's class loader etc.
   // 使用应用上下文的类加载器
   beanFactory.setBeanClassLoader(getClassLoader());
   // 设置bean表达式解析器
   beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
   // 添加属性编辑器注册器
   beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this,getEnvironment()));
   // Configure the bean factory with context callbacks.
   // 使用上下文回调函数配置bean factory
   beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
   beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
   beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
   beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
   beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
   beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
   beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);
   // BeanFactory interface not registered as resolvable type in a plain factory.
   // MessageSource registered (and found for autowiring) as a bean.
   // 注册依赖
   beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
   beanFactory.registerResolvableDependency(ResourceLoader.class, this);
   beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
   beanFactory.registerResolvableDependency(ApplicationContext.class, this);
   // Register early post-processor for detecting inner beans as ApplicationListeners.
   // 添加一个用于探测实现了ApplicationListener接口的bean的后置处理器
   beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));
   // Detect a LoadTimeWeaver and prepare for weaving, if found.
   // 探测LoadTimeWeaver并准备织入,与AOP相关
   if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
       beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
     // Set a temporary ClassLoader for type matching.
     beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
   }
   // Register default environment beans.
   // 将默认环境作为bean注册
   if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {
       beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());
   }
   if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {
       beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());
   }
   if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
       beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());
   }
}

  addBeanPostProcessor()会添加一个ApplicationContextAwareProcessor处理器,这个类实现了BeanPostProcessor接口,同时由于应用上下文持有其它*Aware等的引用,因此在后面的代码中忽略了这些依赖

3.4.4 invokeBeanFactoryPostProcessors()

  该方法会扫描到指定包下标有注解的类,然后将其变成BeanDefinition对象,然后放到一个Spring的Map中,用于后面创建Spring bean的时候使用这个BeanDefinition

protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
   // BeanFactory后置处理器的具体实现
   PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
   // Detect a LoadTimeWeaver and prepare for weaving, if found in the meantime
   // (e.g. through an @Bean method registered by ConfigurationClassPostProcessor)
   if (beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
       beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
       beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
   }
}


  Spring委托PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors实现后置处理,它的具体实现很长,系统启动时就注册了几个后置处理器,如SharedMetadataReaderFactoryContextInitializer,CachingMetadataReaderFactoryPostProcessor等。

  代码的执行思路是:先将后置处理器进行分类,分别是BeanFactoryPostProcessor和BeanDefinitionRegistryPostProcessor,同时将BeanDefinitionRegistry注册为一个BeanDefinition并调用注册表后置处理器的相关方法(与注册表相关);接着,按PriorityOrdered, Ordered和其它的顺序调用手动添加(Spring Boot)的后置处理器。Spring Boot在之前注册过一个ConfigurationClassPostProcessor后置处理器;

  最终这个后置处理器会调用ConfigurationClassPostProcessor#processConfigBeanDefinitions()对配置类进行处理。在处理时需要创建 ConfigurationClassParser对象进行解析,同时会创建一个 ComponentScanAnnotationParser 对象,在这个类中会扫描获取所有带有注解的bean类;

  ConfigurationClassPostProcessor#processConfigBeanDefinitions()具体的思路是先获取所有的bean definition,并找出配置类对应的bean definition。接着对容器进行一下转换并实例化一个ConfigurationClassParser配置类解析器对象parser,调用parser的parse()对配置类进行解析。ConfigurationClassParser#parse()的具体实现如下:


public void parse(Set<BeanDefinitionHolder> configCandidates) {
   this.deferredImportSelectors = new LinkedList<DeferredImportSelectorHolder>();
   for (BeanDefinitionHolder holder : configCandidates) {
       BeanDefinition bd = holder.getBeanDefinition();
       try {
           //如果bean是注解的,则解析注解---Spring Boot基于注解配置
           if (bd instanceof AnnotatedBeanDefinition) {
               parse(((AnnotatedBeanDefinition) bd).getMetadata(), holder.getBeanName());
           }
           // 如果是抽象bean并且有bean类
           else if (bd instanceof AbstractBeanDefinition && ((AbstractBeanDefinition) bd).hasBeanClass()) {
               parse(((AbstractBeanDefinition) bd).getBeanClass(), holder.getBeanName());
         } else {
            // 普通解析
           parse(bd.getBeanClassName(), holder.getBeanName());
         }
       }
       catch (BeanDefinitionStoreException ex) {
           throw ex;
     } catch (Throwable ex) {
         throw new BeanDefinitionStoreException(  "Failed to parse configuration class [" + bd.getBeanClassName() + "]", ex);
     }
   }
     // 处理延迟导入的选择器
     processDeferredImportSelectors();
}


  在处理配置bean时,ConfigurationClassParser#doProcessConfigurationClass()会首先迭代地处理所有嵌套的配置类,然后处理所有的@PropertySource注解来解析属性源,再处理@ComponentScan注解实现自动扫描,再处理@Import注解来导入配置类,注意,@SpringBootApplication注解由@EnableAutoConfiguration注解,而@EnableAutoConfiguration由@Import(EnableAutoConfigurationImportSelector.class)注解,同时它的@AutoConfigurationPackage由@Import(AutoConfigurationPackages.Registrar.class)注解,从这里可以看到@EnableAutoConfiguration默认导入了两个类。

  对@ImportResource注解的处理

  处理@Bean注解的方法不会注册bean,只在配置类中注册相应的方法。

  处理超类

  processDeferredImportSelectors()的具体实现:

private void processDeferredImportSelectors() {
   List<DeferredImportSelectorHolder> deferredImports = this.deferredImportSelectors;
   this.deferredImportSelectors = null;
   Collections.sort(deferredImports, DEFERRED_IMPORT_COMPARATOR);
   for (DeferredImportSelectorHolder deferredImport : deferredImports) {
       ConfigurationClass configClass = deferredImport.getConfigurationClass();
       try {
         // 获取importSelector---在自动配置源数据中删除不符合要求或者无法实例化的对象
         String[] imports = deferredImport.getImportSelector().selectImports(configClass.getMetadata());
         //处理import---迭代处理,最终调用processConfigurationClass处理自动配置的类
         processImports(configClass, asSourceClass(configClass), asSourceClasses(imports), false);
       } catch (BeanDefinitionStoreException ex) {
           throw ex;
       } catch (Throwable ex) {
           throw new BeanDefinitionStoreException("Failed to process import candidates for configuration class [" + configClass.getMetadata().getClassName() + "]", ex);
       }
   }
}

  至此,Spring Boot的自动配置基本完成

3.4.5 registerBeanPostProcessors()

  根据实现了PropertyOrdered,Order接口,排序后注册所有的BeanPostProcessor后置处理器,主要用于创建bean时,执行这些后置处理器的方法,这也是Spring 提供的扩展点,让我们能够插手Spring bean的创建过程。

 

3.4.6 重点 finishBeanFactoryInitialization() 实现SpringBean生命周期过程

  完成所所有单例bean的创建和实例化,其方法调用链如下

AbstractApplicationContext.finishBeanFactoryInitialization(方法最后一行)-----〉
AbstractBeanFactory.getBean---->AbstractBeanFactory.doGetBean------->
AbstractAutowireCapableBeanFactory.createBean------->

重点:AbstractAutowireCapableBeanFactory.doCreateBean(这个方法进行bean的生命周期)

  在实例化Bean的过程中,会按照顺序执行,如下:

  resolveBeforeInstantiation会找到类型为InstantiationAwareBeanPostProcessor,且在Bean初始化前对Bean执行操作,实例化 ----》 AbstractAutowireCapableBeanFactory.doCreateBean() populateBean注入属性initalizeBean方法调用扩展,顺序如下:

  1)如果Bean是BeanNameAware,BeanClassLoaderAware,BeanFactoryAware,会执行者几个的方法Aware的对应方法

  2)先执行所有BeanPostProcessor.postProcessBeforeInitialization()

  3) 反射调用init方法,如果Bean是InitializingBean,会先执行InitializingBean的afterPropertiesSet方法, 然后在执行自动以的init方法

  4)调用所有BeanPostProcessor.applyBeanPostProcessorsAfterInitialization()方法 @PostConstruct标记的方法,是在BeanPostProcessor.postProcessBeforeInitialization() 调用时执行,也就是有一个BeanPostProcessor用于处理标记了该注解的方法(InitDestroyAnnotationBeanPostProcessor),定时器等注解,原理也是一样的,在解析BeanDefinition时,会将这些注解都解析成BeanDefinition的一个属性

  bean生命周期执行过程图如下

 

可以简述为以下九步

  • 实例化bean对象(通过构造方法或者工厂方法)
  • 设置对象属性(setter等)(依赖注入)
  • 如果Bean实现了BeanNameAware接口,工厂调用Bean的setBeanName()方法传递Bean的ID。(和下面的一条均属于检查Aware接口)
  • 如果Bean实现了BeanFactoryAware接口,工厂调用setBeanFactory()方法传入工厂自身
  • 将Bean实例传递给Bean的前置处理器的postProcessBeforeInitialization(Object bean, String beanname)方法
  • 调用Bean的初始化方法; Spring检测对象如果实现InitializingBean这个接口,就会执行他的afterPropertiesSet()方法,定制初始化逻辑。以及进行@PostConstruct注解逻辑实现
  • 将Bean实例传递给Bean的后置处理器的postProcessAfterInitialization(Object bean, String beanname)方法
  • 使用Bean
  • 容器关闭之前,调用Bean的销毁方法

 

标签: spring boot

目录
相关文章
|
6天前
|
存储 缓存 Java
什么是线程池?从底层源码入手,深度解析线程池的工作原理
本文从底层源码入手,深度解析ThreadPoolExecutor底层源码,包括其核心字段、内部类和重要方法,另外对Executors工具类下的四种自带线程池源码进行解释。 阅读本文后,可以对线程池的工作原理、七大参数、生命周期、拒绝策略等内容拥有更深入的认识。
什么是线程池?从底层源码入手,深度解析线程池的工作原理
|
6天前
|
设计模式 Java 关系型数据库
【Java笔记+踩坑汇总】Java基础+JavaWeb+SSM+SpringBoot+SpringCloud+瑞吉外卖/谷粒商城/学成在线+设计模式+面试题汇总+性能调优/架构设计+源码解析
本文是“Java学习路线”专栏的导航文章,目标是为Java初学者和初中高级工程师提供一套完整的Java学习路线。
|
1天前
|
存储 缓存 自然语言处理
深度解析ElasticSearch:构建高效搜索与分析的基石
【9月更文挑战第8天】在数据爆炸的时代,如何快速、准确地从海量数据中检索出有价值的信息成为了企业面临的重要挑战。ElasticSearch,作为一款基于Lucene的开源分布式搜索和分析引擎,凭借其强大的实时搜索、分析和扩展能力,成为了众多企业的首选。本文将深入解析ElasticSearch的核心原理、架构设计及优化实践,帮助读者全面理解这一强大的工具。
27 7
|
10天前
|
开发工具
Flutter-AnimatedWidget组件源码解析
Flutter-AnimatedWidget组件源码解析
|
3月前
|
Java 开发者 Spring
解析Spring中Bean的生命周期
解析Spring中Bean的生命周期
40 2
|
4月前
|
缓存 Java Spring
Spring 框架中 Bean 的生命周期
Spring 框架中 Bean 的生命周期
61 1
|
3月前
|
XML druid Java
Spring5系列学习文章分享---第二篇(IOC的bean管理factory+Bean作用域与生命周期+自动装配+基于注解管理+外部属性管理之druid)
Spring5系列学习文章分享---第二篇(IOC的bean管理factory+Bean作用域与生命周期+自动装配+基于注解管理+外部属性管理之druid)
42 0
|
29天前
|
前端开发 Java 开发者
|
1月前
|
Java Spring
Spring的Bean生命周期中@PostConstruct注解
【8月更文挑战第3天】在Spring框架中,`@PostConstruct`注解标示Bean初始化完成后立即执行的方法。它在依赖注入完成后调用,适用于资源加载、属性设置等初始化操作。若方法中抛出异常,可能影响Bean初始化。与之对应,`@PreDestroy`注解的方法则在Bean销毁前执行,用于资源释放。
|
3月前
|
Java 开发者 Spring
Spring 中 Bean 的生命周期
Spring 中 Bean 的生命周期
26 2

热门文章

最新文章

推荐镜像

更多