讀完這章,你還敢說你不會SpringBoot原始碼?

前言

筆者把之前的Spring的格式重新排版,並且細緻到一行一個講解,希望大家喜歡。

大家使用Spring Boot這麼久了,有沒有知道Spring Boot的啟動流程是怎樣的呢?Spring是如何掃描到使用@Component的類並且把它放進BeanFactory呢?它是如何啟動的呢?現在我們就一起看看。本系列會分幾個章節去講述這個Spring Boot的啟動過程。由於寫這篇文章的時候,在很多環境寫過,所以可能由於Spring Boot版本不同程式碼也不同,但是思路是一樣的。

1。建立SpringApplication物件

// 1。main方法@SpringBootApplication(exclude = DataSourceAutoConfiguration。class)public class DemoApplication { public static void main(String[] args) { // 啟動入口,請點選run方法 SpringApplication。run(DemoApplication。class, args); }}// 2。main方法進來後先建立一個例項new SpringApplication 蹩腳翻譯一下/** * 建立一個新的SpringApplication例項也就是要new SpringApplication(),並且定義主要的類作為Bean的載入來源 *//** * Create a new {@link SpringApplication} instance。 The application context will load * beans from the specified primary sources (see {@link SpringApplication class-level} * documentation for details。 The instance can be customized before calling * {@link #run(String。。。)}。 * @param resourceLoader the resource loader to use * @param primarySources the primary bean sources * @see #run(Class, String[]) * @see #setSources(Set) */@SuppressWarnings({ “unchecked”, “rawtypes” })public SpringApplication(ResourceLoader resourceLoader, Class<?>。。。 primarySources) { this。resourceLoader = resourceLoader; Assert。notNull(primarySources, “PrimarySources must not be null”); // 設定類入口也就是啟動類 this。primarySources = new LinkedHashSet<>(Arrays。asList(primarySources)); // 設定這個應用的型別,分別為SERVLET、NONE、REACTIVE。具體可以看WebApplicationType列舉類 this。webApplicationType = WebApplicationType。deduceFromClasspath(); // 設定初始化器,這個getSpringFactoriesInstances()方法是從spring。factories中讀取 setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer。class)); // 設定監聽器,更上面一樣也就是隻要看到這個方法就是從spring。factories中讀取要的類並且載入 setListeners((Collection) getSpringFactoriesInstances(ApplicationListener。class)); this。mainApplicationClass = deduceMainApplicationClass();}

讀完這章,你還敢說你不會SpringBoot原始碼?

讀完這章,你還敢說你不會SpringBoot原始碼?

讀完這章,你還敢說你不會SpringBoot原始碼?

2。在SpringApplication物件呼叫run()

/** * 1。跑run方法 */public ConfigurableApplicationContext run(String。。。 args) { StopWatch stopWatch = new StopWatch(); // 開啟計時器 stopWatch。start(); ConfigurableApplicationContext context = null; Collection exceptionReporters = new ArrayList<>(); // 配置一些外設 configureHeadlessProperty(); // 獲取監聽器,這個getRunlisteners方法裡面也是一樣獲取監聽器 SpringApplicationRunListeners listeners = getRunListeners(args); // 監聽器開始執行 listeners。starting(); try { ApplicationArguments applicationArguments = new DefaultApplicationArguments(args); ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments); configureIgnoreBeanInfo(environment); // 列印banner Banner printedBanner = printBanner(environment); // 建立應用上下文,請看2 context = createApplicationContext(); // 載入異常報告期 exceptionReporters = getSpringFactoriesInstances(SpringBootExceptionReporter。class, new Class[] { ConfigurableApplicationContext。class }, context); // 準備上下文,請看3 prepareContext(context, environment, listeners, applicationArguments, printedBanner); // 重新整理上下文 refreshContext(context); afterRefresh(context, applicationArguments); stopWatch。stop(); if (this。logStartupInfo) { new StartupInfoLogger(this。mainApplicationClass)。logStarted(getApplicationLog(), stopWatch); } listeners。started(context); callRunners(context, applicationArguments); } catch (Throwable ex) { handleRunFailure(context, ex, exceptionReporters, listeners); throw new IllegalStateException(ex); } try { listeners。running(context); } catch (Throwable ex) { handleRunFailure(context, ex, exceptionReporters, null); throw new IllegalStateException(ex); } return context;}/** * 2。這個方法是從建立SpringApplication例項載入的應用型別去建立不同的上下文例項,這裡由於是SERVLET型別所以會建立 */protected ConfigurableApplicationContext createApplicationContext() { Class<?> contextClass = this。applicationContextClass; if (contextClass == null) { try { switch (this。webApplicationType) { case SERVLET: // org。springframework。boot。web。servlet。context。AnnotationConfigServletWebServerApplicationContext // 叫做註解配置上下文例項(蹩腳翻譯) contextClass = Class。forName(DEFAULT_SERVLET_WEB_CONTEXT_CLASS); break; case REACTIVE: contextClass = Class。forName(DEFAULT_REACTIVE_WEB_CONTEXT_CLASS); break; default: contextClass = Class。forName(DEFAULT_CONTEXT_CLASS); } } catch (ClassNotFoundException ex) { throw new IllegalStateException( “Unable create a default ApplicationContext, please specify an ApplicationContextClass”, ex); } } return (ConfigurableApplicationContext) BeanUtils。instantiateClass(contextClass);}/** * 3。準備上下文,這裡其實挺重要的,講述了啟動類如何載入到BeanFactory * 其實就一個重點,在load()這個方法裡面 */private void prepareContext(ConfigurableApplicationContext context, ConfigurableEnvironment environment, SpringApplicationRunListeners listeners, ApplicationArguments applicationArguments, Banner printedBanner) { context。setEnvironment(environment); postProcessApplicationContext(context); applyInitializers(context); listeners。contextPrepared(context); if (this。logStartupInfo) { logStartupInfo(context。getParent() == null); logStartupProfileInfo(context); } // Add boot specific singleton beans // 這裡context因為是AnnotationConfigServletWebServerApplicationContext // 所以他繼承於ServletWebServerApplicationContext // ServletWebServerApplicationContext繼承GenericWebApplicationContext // GenericWebApplicationContext繼承GenericApplicationContext // 所以他的beanFactory是預設的private final DefaultListableBeanFactory beanFactory; ConfigurableListableBeanFactory beanFactory = context。getBeanFactory(); beanFactory。registerSingleton(“springApplicationArguments”, applicationArguments); if (printedBanner != null) { beanFactory。registerSingleton(“springBootBanner”, printedBanner); } if (beanFactory instanceof DefaultListableBeanFactory) { ((DefaultListableBeanFactory) beanFactory) 。setAllowBeanDefinitionOverriding(this。allowBeanDefinitionOverriding); } if (this。lazyInitialization) { context。addBeanFactoryPostProcessor(new LazyInitializationBeanFactoryPostProcessor()); } // Load the sources Set sources = getAllSources(); Assert。notEmpty(sources, “Sources must not be empty”); // 這個方法講述了啟動類如何註冊到beanFactory裡面,為下面的refreshContext做了鋪墊 // 而且這個load方法裡面還有啟動類如何註冊到BeanDefinition裡面去的,去看4 load(context, sources。toArray(new Object[0])); listeners。contextLoaded(context);}/** * 4。這裡就先說下doRegisterBean() * 每個bean被執行doGetBean方法前都是要把Bean的定義資訊拿到,也就是通俗的BeanDefinition,類的元資料 * 而AnnotatedGenericBeanDefinition就是為了公開這些類元資料做的介面 * 當adb和beanName一起在BeanDefinitionHolder初始化的時候 */private void doRegisterBean(Class beanClass, @Nullable String name, @Nullable Class<? extends Annotation>[] qualifiers, @Nullable Supplier supplier, @Nullable BeanDefinitionCustomizer[] customizers) { // 定義bean的元資料物件,下面都是獲取bean名字之類的 AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(beanClass); if (this。conditionEvaluator。shouldSkip(abd。getMetadata())) { return; } abd。setInstanceSupplier(supplier); ScopeMetadata scopeMetadata = this。scopeMetadataResolver。resolveScopeMetadata(abd); abd。setScope(scopeMetadata。getScopeName()); String beanName = (name != null ? name : this。beanNameGenerator。generateBeanName(abd, this。registry)); AnnotationConfigUtils。processCommonDefinitionAnnotations(abd); if (qualifiers != null) { for (Class<? extends Annotation> qualifier : qualifiers) { if (Primary。class == qualifier) { abd。setPrimary(true); } else if (Lazy。class == qualifier) { abd。setLazyInit(true); } else { abd。addQualifier(new AutowireCandidateQualifier(qualifier)); } } } if (customizers != null) { for (BeanDefinitionCustomizer customizer : customizers) { customizer。customize(abd); } } // 當元資料物件與beanName建立了BeanDefinitionHolder // 他會把一些alias和beanName全部儲存下來 BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName); definitionHolder = AnnotationConfigUtils。applyScopedProxyMode(scopeMetadata, definitionHolder, this。registry); // 這裡就會正式把此bean註冊到this。beanDefinitionMap和this。beanDefinitionNames屬性裡面 // 而這兩個屬性就是剛剛的預設beanFactory也就是DefaultListableBeanFactory。class BeanDefinitionReaderUtils。registerBeanDefinition(definitionHolder, this。registry);}

3。核心方法refreshContext

/** * 1。此方法其實就是Spring整個啟動過程或者說ioc等等的核心流程了 * 這個方法分幾步去講解 */public void refresh() throws BeansException, IllegalStateException { synchronized (this。startupShutdownMonitor) { // Prepare this context for refreshing。 // 準備上下文 prepareRefresh(); // Tell the subclass to refresh the internal bean factory。 ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); // Prepare the bean factory for use in this context。 prepareBeanFactory(beanFactory); try { // Allows post-processing of the bean factory in context subclasses。 postProcessBeanFactory(beanFactory); // Invoke factory processors registered as beans in the context。 // 這個方法是掃描所有的Bean和載入所有的Bean invokeBeanFactoryPostProcessors(beanFactory); // 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(); } }}/** * 2。這裡進來就是beanFactory增強器載入 */protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) { // getBeanFactoryPostProcessors()這個方法就是獲取當前所有的beanFactory增強器進去可以看看,目前預設有3個 // 1。SharedMetadataReaderFactoryContextInitializer$CachingMetadataReaderFactoryPostProcessor在prepareContext中的applyInitializers插入 // 2。ConfigurationWarningsApplicationContextInitializer$ConfigurationWarningsPostProcessor在prepareContext中的applyInitializers插入 // 3。ConfigFileApplicationListener$PropertySourceOrderingPostProcessor在prepareContext最後一行listeners。contextLoaded(context)插入 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())); }}/** * 3。這方法重中之重,裡面包涵了大量的操作我們來一起看看 */public static void invokeBeanFactoryPostProcessors( ConfigurableListableBeanFactory beanFactory, List beanFactoryPostProcessors) { // Invoke BeanDefinitionRegistryPostProcessors first, if any。 Set processedBeans = new HashSet<>(); // 這個context是AnnotationConfigServletWebServerApplicationContext例項他繼承的類有BeanDefinitionRegistry介面 // 所以這裡一定會進來 if (beanFactory instanceof BeanDefinitionRegistry) { BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory; List regularPostProcessors = new ArrayList<>(); List registryProcessors = new ArrayList<>(); // 這個迴圈是把那3個增強器分類 // CachingMetadataReaderFactoryPostProcessor實現BeanDefinitionRegistryPostProcessor // ConfigurationWarningsPostProcesso實現BeanDefinitionRegistryPostProcessor // PropertySourceOrderingPostProcessor實現BeanFactoryPostProcessor for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) { if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) { BeanDefinitionRegistryPostProcessor registryProcessor = (BeanDefinitionRegistryPostProcessor) postProcessor; // 這裡把BeanDefinition註冊進去 registryProcessor。postProcessBeanDefinitionRegistry(registry); registryProcessors。add(registryProcessor); } else { regularPostProcessors。add(postProcessor); } } // Do not initialize FactoryBeans here: We need to leave all regular beans // uninitialized to let the bean factory post-processors apply to them! // Separate between BeanDefinitionRegistryPostProcessors that implement // PriorityOrdered, Ordered, and the rest。 List currentRegistryProcessors = new ArrayList<>(); // First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered。 // 這裡獲取到的beanName不是剛剛的增強器而是常量org。springframework。context。annotation。internalConfigurationAnnotationProcessor // 並且下面這個迴圈會把ConfigurationClassPostProcessor加載出來。 // 那麼大家會問ConfigurationClassPostProcessor什麼時候載入的呢? // createApplicationContext這個方法還記得吧!就是在這裡載入的當Spring選擇了Servlet模式就會載入配置 // CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME就會作為beanNamePut進beanFactory String[] postProcessorNames = beanFactory。getBeanNamesForType(BeanDefinitionRegistryPostProcessor。class, true, false); for (String ppName : postProcessorNames) { if (beanFactory。isTypeMatch(ppName, PriorityOrdered。class)) { currentRegistryProcessors。add(beanFactory。getBean(ppName, BeanDefinitionRegistryPostProcessor。class)); processedBeans。add(ppName); } } sortPostProcessors(currentRegistryProcessors, beanFactory); registryProcessors。addAll(currentRegistryProcessors); // 當ConfigurationClassPostProcessor回去跑processConfigBeanDefinitions方法,跳去4 invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry); currentRegistryProcessors。clear(); // Next, invoke the BeanDefinitionRegistryPostProcessors that implement Ordered。 postProcessorNames = beanFactory。getBeanNamesForType(BeanDefinitionRegistryPostProcessor。class, true, false); for (String ppName : postProcessorNames) { if (!processedBeans。contains(ppName) && beanFactory。isTypeMatch(ppName, Ordered。class)) { currentRegistryProcessors。add(beanFactory。getBean(ppName, BeanDefinitionRegistryPostProcessor。class)); processedBeans。add(ppName); } } sortPostProcessors(currentRegistryProcessors, beanFactory); registryProcessors。addAll(currentRegistryProcessors); invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry); currentRegistryProcessors。clear(); // Finally, invoke all other BeanDefinitionRegistryPostProcessors until no further ones appear。 boolean reiterate = true; while (reiterate) { reiterate = false; postProcessorNames = beanFactory。getBeanNamesForType(BeanDefinitionRegistryPostProcessor。class, true, false); for (String ppName : postProcessorNames) { if (!processedBeans。contains(ppName)) { currentRegistryProcessors。add(beanFactory。getBean(ppName, BeanDefinitionRegistryPostProcessor。class)); processedBeans。add(ppName); reiterate = true; } } sortPostProcessors(currentRegistryProcessors, beanFactory); registryProcessors。addAll(currentRegistryProcessors); invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry); currentRegistryProcessors。clear(); } // Now, invoke the postProcessBeanFactory callback of all processors handled so far。 invokeBeanFactoryPostProcessors(registryProcessors, beanFactory); invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory); } else { // Invoke factory processors registered with the context instance。 invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory); } // Do not initialize FactoryBeans here: We need to leave all regular beans // uninitialized to let the bean factory post-processors apply to them! String[] postProcessorNames = beanFactory。getBeanNamesForType(BeanFactoryPostProcessor。class, true, false); // Separate between BeanFactoryPostProcessors that implement PriorityOrdered, // Ordered, and the rest。 List priorityOrderedPostProcessors = new ArrayList<>(); List orderedPostProcessorNames = new ArrayList<>(); List nonOrderedPostProcessorNames = new ArrayList<>(); for (String ppName : postProcessorNames) { if (processedBeans。contains(ppName)) { // skip - already processed in first phase above } else if (beanFactory。isTypeMatch(ppName, PriorityOrdered。class)) { priorityOrderedPostProcessors。add(beanFactory。getBean(ppName, BeanFactoryPostProcessor。class)); } else if (beanFactory。isTypeMatch(ppName, Ordered。class)) { orderedPostProcessorNames。add(ppName); } else { nonOrderedPostProcessorNames。add(ppName); } } // First, invoke the BeanFactoryPostProcessors that implement PriorityOrdered。 sortPostProcessors(priorityOrderedPostProcessors, beanFactory); invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory); // Next, invoke the BeanFactoryPostProcessors that implement Ordered。 List orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames。size()); for (String postProcessorName : orderedPostProcessorNames) { orderedPostProcessors。add(beanFactory。getBean(postProcessorName, BeanFactoryPostProcessor。class)); } sortPostProcessors(orderedPostProcessors, beanFactory); invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory); // Finally, invoke all other BeanFactoryPostProcessors。 List nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames。size()); for (String postProcessorName : nonOrderedPostProcessorNames) { nonOrderedPostProcessors。add(beanFactory。getBean(postProcessorName, BeanFactoryPostProcessor。class)); } invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory); // Clear cached merged bean definitions since the post-processors might have // modified the original metadata, e。g。 replacing placeholders in values。。。 beanFactory。clearMetadataCache();}/** * 4。這裡就是把啟動類選出來並且開始ComponentScan的地方,自動裝配也是這裡完成的@Import */public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) { List configCandidates = new ArrayList<>(); String[] candidateNames = registry。getBeanDefinitionNames(); //configCandidates這會加入啟動類 for (String beanName : candidateNames) { BeanDefinition beanDef = registry。getBeanDefinition(beanName); if (beanDef。getAttribute(ConfigurationClassUtils。CONFIGURATION_CLASS_ATTRIBUTE) != null) { if (logger。isDebugEnabled()) { logger。debug(“Bean definition has already been processed as a configuration class: ” + beanDef); } } else if (ConfigurationClassUtils。checkConfigurationClassCandidate(beanDef, this。metadataReaderFactory)) { configCandidates。add(new BeanDefinitionHolder(beanDef, beanName)); } } /** * 省略程式碼 */ // Parse each @Configuration class // 這就是找Component的實現類 ConfigurationClassParser parser = new ConfigurationClassParser( this。metadataReaderFactory, this。problemReporter, this。environment, this。resourceLoader, this。componentScanBeanNameGenerator, registry); Set candidates = new LinkedHashSet<>(configCandidates); Set alreadyParsed = new HashSet<>(configCandidates。size()); do { // 這個是重點parse有很多Component類這裡用來 parser。parse(candidates); /** * 省略程式碼 */ } while (!candidates。isEmpty()); /** * 省略程式碼 */}/** * 5。掃描Component和自動裝配,這個也很重要,而且段程式碼有幾個遞迴也是比較複雜 * 也是希望大家能夠自己debug進去看看這到底是如何遞迴的 */protected final SourceClass doProcessConfigurationClass( ConfigurationClass configClass, SourceClass sourceClass, Predicate filter) throws IOException { /** * 省略程式碼 */ // Process any @ComponentScan annotations // 這個為什麼是陣列呢?當你使用@ComponentScans(value = {@ComponentScan(“com。example。test”), @ComponentScan(“com。example。test1”)}) // 這裡的長度就會變成3 Set componentScans = AnnotationConfigUtils。attributesForRepeatable( sourceClass。getMetadata(), ComponentScans。class, ComponentScan。class); if (!componentScans。isEmpty() && !this。conditionEvaluator。shouldSkip(sourceClass。getMetadata(), ConfigurationPhase。REGISTER_BEAN)) { // 開始以啟動類掃描,這就是為什麼啟動類永遠在所有包的最外層,如果要掃描其他模組或者啟動類以外的包就要@ScanComponent這個註解 for (AnnotationAttributes componentScan : componentScans) { // The config class is annotated with @ComponentScan -> perform the scan immediately // 這裡面就開始掃描doScan方法,只要是有@Component註解的都會把每個類的Definition放到scannedBeanDefinitions裡面 Set scannedBeanDefinitions = this。componentScanParser。parse(componentScan, sourceClass。getMetadata()。getClassName()); // Check the set of scanned definitions for any further config classes and parse recursively if needed for (BeanDefinitionHolder holder : scannedBeanDefinitions) { BeanDefinition bdCand = holder。getBeanDefinition()。getOriginatingBeanDefinition(); if (bdCand == null) { bdCand = holder。getBeanDefinition(); } if (ConfigurationClassUtils。checkConfigurationClassCandidate(bdCand, this。metadataReaderFactory)) { // 這裡有事解析這個Bean,跟剛剛的parser。parse一樣,只是一個是陣列一個是單個Bean // 並且他會遞迴呼叫doProcessConfigurationClass()方法,並且重新執行一次獲取看看這個類有沒有@ComponentScan,並且繼續掃描直至結束 parse(bdCand。getBeanClassName(), holder。getBeanName()); } } } } // Process any @Import annotations // 其實每一個parse方法都會走到這裡,把每個類的註解都會去迴圈一次,直至沒有註解位置,會把@Import註解的類全部加載出來,這就是自動裝配的原理 // 這就是為什麼我其他jar包的類可以給Spring管理@Import就是一個重點,把這個類匯入到BeanFactory裡面 processImports(configClass, sourceClass, getImports(sourceClass), filter, true); /** * 省略程式碼 */ return null; }

建立Bean例項

/** * 建立bean例項,這裡的方法過於複雜用文章非常難解釋,筆者這裡就把大致的思路說下 * 1。getBean的時候先去createBean如果有就返回沒有的話doCreateBean * 2。當doCreateBean的時候就會觸發bean的生命週期的各個介面 * 3。其實筆者發現一個東西,ApplicationContextAware並不算是bean生命週期的一環把,而是輸入上下文的一環 * 4。因為ApplicationContextAware其實是由添加了AnnotationConfigServletWebServerApplicationContext類所導致的 * 5。建立bean的我會有下面的uml圖讓大家更能理解Bean是如何建立的 */public void preInstantiateSingletons() throws BeansException { if (logger。isTraceEnabled()) { logger。trace(“Pre-instantiating singletons in ” + this); } // Iterate over a copy to allow for init methods which in turn register new bean definitions。 // While this may not be part of the regular factory bootstrap, it does otherwise work fine。 List beanNames = new ArrayList<>(this。beanDefinitionNames); // Trigger initialization of all non-lazy singleton beans。。。 // 獲取所有的BeanName for (String beanName : beanNames) { RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName); if (!bd。isAbstract() && bd。isSingleton() && !bd。isLazyInit()) { if (isFactoryBean(beanName)) { Object bean = getBean(FACTORY_BEAN_PREFIX + beanName); if (bean instanceof FactoryBean) { final FactoryBean<?> factory = (FactoryBean<?>) bean; boolean isEagerInit; if (System。getSecurityManager() != null && factory instanceof SmartFactoryBean) { isEagerInit = AccessController。doPrivileged((PrivilegedAction) ((SmartFactoryBean<?>) factory)::isEagerInit, getAccessControlContext()); } else { isEagerInit = (factory instanceof SmartFactoryBean && ((SmartFactoryBean<?>) factory)。isEagerInit()); } if (isEagerInit) { getBean(beanName); } } } else { getBean(beanName); } } } // Trigger post-initialization callback for all applicable beans。。。 for (String beanName : beanNames) { Object singletonInstance = getSingleton(beanName); if (singletonInstance instanceof SmartInitializingSingleton) { final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance; if (System。getSecurityManager() != null) { AccessController。doPrivileged((PrivilegedAction) () -> { smartSingleton。afterSingletonsInstantiated(); return null; }, getAccessControlContext()); } else { smartSingleton。afterSingletonsInstantiated(); } } } }

關於ApplicationContext

實現ApplicationContextAware介面會呼叫setApplicationContext方法,而ApplicationContextAwareProcessor又是實現BeanPostProcessor,而ApplicationContextAwareProcessor又被Spring強制註冊,所以說如果一個Bean實現ApplicationContextAware和BeanPostProcessor,在先初始化有關於BeanPostProcessor的Bean時候會建立這個Bean建立這個Bean的時候又會呼叫setApplicationContext方法呼叫完之後最後才會呼叫BeanPostProcessor實現的方法,其實聽拗口的,所以最後還是希望自己能Debug一下

bean生命週期流程圖

讀完這章,你還敢說你不會SpringBoot原始碼?

小結

當我重新重構這篇文章的時候,其實是因為我自己都讀不懂之前的文章,希望這章大家可以看得懂。大家讀不懂肯定是說明我的文采還不夠好,也希望大家多多指出筆者的錯誤。

說到Spring其實在座的各位都是Spring工程師,老搬磚奴,但是大家肯定也因為忙沒時間去研究整個Spring的流程。這裡筆者幫大家都全部準備好了。