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

转载请注明出处:

 

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的销毁方法

 

posted @ 2022-05-03 22:23  香吧香  阅读(421)  评论(0编辑  收藏  举报