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的注册细节后面分析。