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

 

posted @ 2019-03-18 14:09  Over_Watch  阅读(1282)  评论(0编辑  收藏  举报