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

     

  • 相关阅读:
    500报错解决了
    设计模式(十一)----结构型模式之装饰者模式
    多任务学习的二分类数据该怎么合并和处理?
    docker试验步骤与截图(无用)
    超硬核的Move Dev Meetup上海线下交流会圆满结束
    iText7画发票PDF——小tips
    log4j.properties支持不同包日志分文件打印
    Linux安装Ansible管理工具
    《Maven入门基础》
    【计算机组成原理】CRC码
  • 原文地址:https://www.cnblogs.com/zjdxr-up/p/16219720.html