• spring boot启动源码分析 refreshContext


    prepareContext(context, environment, listeners, applicationArguments, printedBanner);
    refreshContext(context);

    准备阶段

     1     private void prepareContext(ConfigurableApplicationContext context,
     2             ConfigurableEnvironment environment, SpringApplicationRunListeners listeners,
     3             ApplicationArguments applicationArguments, Banner printedBanner) {
     4         context.setEnvironment(environment);
     5         postProcessApplicationContext(context);
     6         applyInitializers(context);
     7         listeners.contextPrepared(context);
     8         if (this.logStartupInfo) {
     9             logStartupInfo(context.getParent() == null);
    10             logStartupProfileInfo(context);
    11         }
    12 
    13         // Add boot specific singleton beans
    14         context.getBeanFactory().registerSingleton("springApplicationArguments",
    15                 applicationArguments);
    16         if (printedBanner != null) {
    17             context.getBeanFactory().registerSingleton("springBootBanner", printedBanner);
    18         }
    19 
    20         // Load the sources
    21         Set<Object> sources = getSources();
    22         Assert.notEmpty(sources, "Sources must not be empty");
    23         load(context, sources.toArray(new Object[sources.size()]));
    24         listeners.contextLoaded(context);
    25     }

    准备阶段会把加载好的environment放到context里面,应用之前加载好的Initializers,EventPublishingRunListener发布上下文准备好的事件,注册springApplicationArguments和springBootBanner(注册单例用的下图的DefaultSingletonBeanRegistry,注册到singletonObjects里面),然后加载sources,这时资源只有入口的application类,最后发布contextLoaded事件。发布的事件由meta-info下的几个listeners接收处理,也可以自定义,放在meta-info下面配置好即可。

     现在开始分析核心的refreshContext(context)方法。

     1     public void refresh() throws BeansException, IllegalStateException {
     2         synchronized (this.startupShutdownMonitor) {
     3             // Prepare this context for refreshing.
     4             prepareRefresh();
     5 
     6             // Tell the subclass to refresh the internal bean factory.
     7             ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
     8 
     9             // Prepare the bean factory for use in this context.
    10             prepareBeanFactory(beanFactory);
    11 
    12             try {
    13                 // Allows post-processing of the bean factory in context subclasses.
    14                 postProcessBeanFactory(beanFactory);
    15 
    16                 // Invoke factory processors registered as beans in the context.
    17                 invokeBeanFactoryPostProcessors(beanFactory);
    18 
    19                 // Register bean processors that intercept bean creation.
    20                 registerBeanPostProcessors(beanFactory);
    21 
    22                 // Initialize message source for this context.
    23                 initMessageSource();
    24 
    25                 // Initialize event multicaster for this context.
    26                 initApplicationEventMulticaster();
    27 
    28                 // Initialize other special beans in specific context subclasses.
    29                 onRefresh();
    30 
    31                 // Check for listener beans and register them.
    32                 registerListeners();
    33 
    34                 // Instantiate all remaining (non-lazy-init) singletons.
    35                 finishBeanFactoryInitialization(beanFactory);
    36 
    37                 // Last step: publish corresponding event.
    38                 finishRefresh();
    39             }
    40 
    41             catch (BeansException ex) {
    42                 if (logger.isWarnEnabled()) {
    43                     logger.warn("Exception encountered during context initialization - " +
    44                             "cancelling refresh attempt: " + ex);
    45                 }
    46 
    47                 // Destroy already created singletons to avoid dangling resources.
    48                 destroyBeans();
    49 
    50                 // Reset 'active' flag.
    51                 cancelRefresh(ex);
    52 
    53                 // Propagate exception to caller.
    54                 throw ex;
    55             }
    56 
    57             finally {
    58                 // Reset common introspection caches in Spring's core, since we
    59                 // might not ever need metadata for singleton beans anymore...
    60                 resetCommonCaches();
    61             }
    62         }
    63     }

    这段refresh方法位于AbstractApplicationContext这个类。

    代码7、10获取之前准备好的beanFactory并初始化。

    代码17会创建BeanDefinitions。

     1 protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
     2         PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
     3 
     4         // Detect a LoadTimeWeaver and prepare for weaving, if found in the meantime
     5         // (e.g. through an @Bean method registered by ConfigurationClassPostProcessor)
     6         if (beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
     7             beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
     8             beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
     9         }
    10     }

    其中ConfigurationPostClassProcessor会创建BeanDefinitions

     1     public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
     2         int registryId = System.identityHashCode(registry);
     3         if (this.registriesPostProcessed.contains(registryId)) {
     4             throw new IllegalStateException(
     5                     "postProcessBeanDefinitionRegistry already called on this post-processor against " + registry);
     6         }
     7         if (this.factoriesPostProcessed.contains(registryId)) {
     8             throw new IllegalStateException(
     9                     "postProcessBeanFactory already called on this post-processor against " + registry);
    10         }
    11         this.registriesPostProcessed.add(registryId);
    12 
    13         processConfigBeanDefinitions(registry);
    14     }
     1     public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
     2         List<BeanDefinitionHolder> configCandidates = new ArrayList<BeanDefinitionHolder>();
     3         String[] candidateNames = registry.getBeanDefinitionNames();
     4 
     5         for (String beanName : candidateNames) {
     6             BeanDefinition beanDef = registry.getBeanDefinition(beanName);
     7             if (ConfigurationClassUtils.isFullConfigurationClass(beanDef) ||
     8                     ConfigurationClassUtils.isLiteConfigurationClass(beanDef)) {
     9                 if (logger.isDebugEnabled()) {
    10                     logger.debug("Bean definition has already been processed as a configuration class: " + beanDef);
    11                 }
    12             }
    13             else if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) {
    14                 configCandidates.add(new BeanDefinitionHolder(beanDef, beanName));
    15             }
    16         }
    17 
    18         // Return immediately if no @Configuration classes were found
    19         if (configCandidates.isEmpty()) {
    20             return;
    21         }
    22 
    23         // Sort by previously determined @Order value, if applicable
    24         Collections.sort(configCandidates, new Comparator<BeanDefinitionHolder>() {
    25             @Override
    26             public int compare(BeanDefinitionHolder bd1, BeanDefinitionHolder bd2) {
    27                 int i1 = ConfigurationClassUtils.getOrder(bd1.getBeanDefinition());
    28                 int i2 = ConfigurationClassUtils.getOrder(bd2.getBeanDefinition());
    29                 return (i1 < i2) ? -1 : (i1 > i2) ? 1 : 0;
    30             }
    31         });
    32 
    33         // Detect any custom bean name generation strategy supplied through the enclosing application context
    34         SingletonBeanRegistry sbr = null;
    35         if (registry instanceof SingletonBeanRegistry) {
    36             sbr = (SingletonBeanRegistry) registry;
    37             if (!this.localBeanNameGeneratorSet && sbr.containsSingleton(CONFIGURATION_BEAN_NAME_GENERATOR)) {
    38                 BeanNameGenerator generator = (BeanNameGenerator) sbr.getSingleton(CONFIGURATION_BEAN_NAME_GENERATOR);
    39                 this.componentScanBeanNameGenerator = generator;
    40                 this.importBeanNameGenerator = generator;
    41             }
    42         }
    43 
    44         // Parse each @Configuration class
    45         ConfigurationClassParser parser = new ConfigurationClassParser(
    46                 this.metadataReaderFactory, this.problemReporter, this.environment,
    47                 this.resourceLoader, this.componentScanBeanNameGenerator, registry);
    48 
    49         Set<BeanDefinitionHolder> candidates = new LinkedHashSet<BeanDefinitionHolder>(configCandidates);
    50         Set<ConfigurationClass> alreadyParsed = new HashSet<ConfigurationClass>(configCandidates.size());
    51         do {
    52             parser.parse(candidates);
    53             parser.validate();
    54 
    55             Set<ConfigurationClass> configClasses = new LinkedHashSet<ConfigurationClass>(parser.getConfigurationClasses());
    56             configClasses.removeAll(alreadyParsed);
    57 
    58             // Read the model and create bean definitions based on its content
    59             if (this.reader == null) {
    60                 this.reader = new ConfigurationClassBeanDefinitionReader(
    61                         registry, this.sourceExtractor, this.resourceLoader, this.environment,
    62                         this.importBeanNameGenerator, parser.getImportRegistry());
    63             }
    64             this.reader.loadBeanDefinitions(configClasses);
    65             alreadyParsed.addAll(configClasses);
    66 
    67             candidates.clear();
    68             if (registry.getBeanDefinitionCount() > candidateNames.length) {
    69                 String[] newCandidateNames = registry.getBeanDefinitionNames();
    70                 Set<String> oldCandidateNames = new HashSet<String>(Arrays.asList(candidateNames));
    71                 Set<String> alreadyParsedClasses = new HashSet<String>();
    72                 for (ConfigurationClass configurationClass : alreadyParsed) {
    73                     alreadyParsedClasses.add(configurationClass.getMetadata().getClassName());
    74                 }
    75                 for (String candidateName : newCandidateNames) {
    76                     if (!oldCandidateNames.contains(candidateName)) {
    77                         BeanDefinition bd = registry.getBeanDefinition(candidateName);
    78                         if (ConfigurationClassUtils.checkConfigurationClassCandidate(bd, this.metadataReaderFactory) &&
    79                                 !alreadyParsedClasses.contains(bd.getBeanClassName())) {
    80                             candidates.add(new BeanDefinitionHolder(bd, candidateName));
    81                         }
    82                     }
    83                 }
    84                 candidateNames = newCandidateNames;
    85             }
    86         }
    87         while (!candidates.isEmpty());
    88 
    89         // Register the ImportRegistry as a bean in order to support ImportAware @Configuration classes
    90         if (sbr != null) {
    91             if (!sbr.containsSingleton(IMPORT_REGISTRY_BEAN_NAME)) {
    92                 sbr.registerSingleton(IMPORT_REGISTRY_BEAN_NAME, parser.getImportRegistry());
    93             }
    94         }
    95 
    96         if (this.metadataReaderFactory instanceof CachingMetadataReaderFactory) {
    97             ((CachingMetadataReaderFactory) this.metadataReaderFactory).clearCache();
    98         }
    99     }

    方法比较长,简单的说就是通过转换器获取到所有的需要注入的class源文件configClasses ,将configClasses 转换成BeanDefinition保存在上下文中。

    registerBeanPostProcessors(beanFactory);会根据BeanDefinition创建Bean,存在singletonObjects中。initMessageSource()初始化国际化相关内容。

    initApplicationEventMulticaster();初始化事件监听器。

    onRefresh()创建内置的Servlet容器。

    registerListeners();把所有的listeners放到事件监听器里。

    finishBeanFactoryInitialization(beanFactory);除了lazy load以外所有的bean都实例化。

    finishRefresh();初始化生命周期处理器,并调用ooRefresh方法,找到所有实现SmartLifecycle接口的类并调用start方法,发布事件告知listener,最后一步LiveBeansView.registerApplicationContext(this);(貌似和JMX有关,JMX后面再做分析)。

    最终重置缓存。

    至此refreshContext已经完成,bean的注册细节后面分析。

  • 相关阅读:
    Geogebra指令
    大表修改表结构
    mongodb获取配置参数getParameter
    mysql的binlog增量日志解析,提供增量数据订阅和消费
    chaosblade-exec-os项目的burnio.go文件解读
    mysql的where条件中的字段不要加函数
    mysql释放大表空间的正确之道
    mysql服务器问题
    purge binary logs to 'mysql-bin.039790';
    golang操作mysql数据库的规范
  • 原文地址:https://www.cnblogs.com/avalon-merlin/p/10544535.html
Copyright © 2020-2023  润新知