1.構造SpringApplication對象
- 推測web應用類型this.webApplicationType(NONE识椰、REACTIVE慧邮、SERVLET)
- 2.從spring.factories中獲取BootstrapRegistryInitializer對象this.bootstrapRegistryInitializers
- 3.從spring.factories中獲取ApplicationContextInitializer對象this.initializers
- 4.從spring.factories中獲取ApplicationListener對象this.listeners
- 5.推測出Main類(main()方法所在的類)this.mainApplicationClass
2.SpringApplication#run:發(fā)布ApplicationStartingEvent
6.從spring.factories中獲取SpringApplicationRunListener對象。默認會拿到一個EventPublishingRunListener府适,它會啟動過程的各個階段發(fā)布對應的ApplicationEvent事件
7.listeners.starting(bootstrapContext, this.mainApplicationClass);發(fā)布ApplicationStartingEvent
3.SpringApplication#run:獲取各種配置參數(shù)
8.將run()的參數(shù)封裝為DefaultApplicationArguments對象
- ConfigurableEnvironment environment = prepareEnvironment(listeners, bootstrapContext, applicationArguments);準備Environment:包括操作系統(tǒng)勿侯,JVM烈炭、ServletContext榜掌、properties优妙、yaml等等配置,會發(fā)布一個ApplicationEnvironmentPreparedEvent
?A)configFileApplicationListener.Loader#load憎账,這里會調用各種文件加載器加載配置文件套硼,比如PropertiesPropertySourceLoader加載properties配置文件
- ConfigurableEnvironment environment = prepareEnvironment(listeners, bootstrapContext, applicationArguments);準備Environment:包括操作系統(tǒng)勿侯,JVM烈炭、ServletContext榜掌、properties优妙、yaml等等配置,會發(fā)布一個ApplicationEnvironmentPreparedEvent
特別注意:
- prepareEnvironment,prepareContext胞皱,refreshContext會被調用兩次邪意,生成父子容器
- 父容器Bootstrap ApplicationContext:Spring Cloud容器,由監(jiān)聽器創(chuàng)建反砌,用來初始化Spring Cloud上下文(此時使用的是bootstrap.properties配置文件)
- 子容器SpringBoot ApplicationContext:平時用的就是SpringBoot容器雾鬼。在創(chuàng)建SpringBoot容器prepareContext()階段,調用PropertySourceBootstrapConfiguration#Initialize()會加載配置并合并到CompositePropertySource宴树。
4.SpringApplication#run:根據(jù)應用類型創(chuàng)建Spring容器
- 10.context = createApplicationContext();
AnnotationConfigServletWebServerApplicationContext
public AnnotationConfigServletWebServerApplicationContext() {
this.reader = new AnnotatedBeanDefinitionReader(this);
this.scanner = new ClassPathBeanDefinitionScanner(this);
}
完整構造過程:
- 調用父類GenericApplicationContext的無參構造方法呆贿,會構造一個BeanFactory,為DefaultListableBeanFactory森渐。
- 構造AnnotatedBeanDefinitionReader(主要作用添加一些基礎的PostProcessor,同時可以通過reader進行BeanDefinition的注冊)冒晰,同時對BeanFactory進行設置和添加PostProcessor(后置處理器)
?1)this.conditionEvaluator = new ConditionEvaluator(registry, environment, null);
?2)設置dependencyComparator:AnnotationAwareOrderComparator同衣,它是一個Comparator,是用來進行排序的壶运,會獲取某個對象上的Order注解或者通過實現(xiàn)Ordered接口所定義的值進行排序耐齐,在日常開發(fā)中可以利用這個類來進行排序。
?3)設置autowireCandidateResolver:ContextAnnotationAutowireCandidateResolver蒋情,用來解析某個Bean能不能進行自動注入埠况,比如某個Bean的autowireCandidate屬性是否等于true
?4)向BeanFactory中添加ConfigurationClassPostProcessor對應的BeanDefinition,它是一個BeanDefinitionRegistryPostProcessor棵癣,并且實現(xiàn)了PriorityOrdered接口
?5)向BeanFactory中添加AutowiredAnnotationBeanPostProcessor對應的BeanDefinition辕翰,它是一個InstantiationAwareBeanPostProcessorAdapter,MergedBeanDefinitionPostProcessor
?6)向BeanFactory中添加CommonAnnotationBeanPostProcessor對應的BeanDefinition狈谊,它是一個InstantiationAwareBeanPostProcessor喜命,InitDestroyAnnotationBeanPostProcessor
?7)向BeanFactory中添加EventListenerMethodProcessor對應的BeanDefinition沟沙,它是一個BeanFactoryPostProcessor,SmartInitializingSingleton
?8)向BeanFactory中添加DefaultEventListenerFactory對應的BeanDefinition壁榕,它是一個EventListenerFactory - 構造ClassPathBeanDefinitionScanner(主要作用可以用來掃描得到并注冊BeanDefinition)矛紫,同時進行設置:
?1)設置this.includeFilters = AnnotationTypeFilter(Component.class)
?2)設置environment
?3)設置resourceLoader
5.SpringApplication#run:prepareContext
- 11.prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner);
1)利用ApplicationContextInitializer初始化Spring容器
2)發(fā)布ApplicationContextInitializedEvent
3)關閉DefaultBootstrapContext
4)注冊primarySources類(BeanDefinition),就是run方法存入進來的配置類
AnnotatedBeanDefinitionReader#register
5)發(fā)布ApplicationPreparedEvent事件
在創(chuàng)建子容器SpringBoot容器prepareContext()階段牌里,調用PropertySourceBootstrapConfiguration#Initialize()會加載配置并合并到CompositePropertySource颊咬。
NacosPropertySourceLocator#locate會從Nacos Config配置中心拉取配置。
6.SpringApplication#run:refreshContext
- 12.refreshContext(context);刷新Spring容器牡辽,會解析配置類喳篇、掃描、啟動WebServer催享、創(chuàng)建單例非懶加載的Bean
6.1 prepareRefresh();
- initPropertySources();可以允許子容器設置一些內容到Environment中:AbstractRefreshableWebApplicationContext#initPropertySources重寫了initPropertySources()杭隙,把web.xml中的配置也加載到Environment中。
-> GenericWebApplicationContext#initPropertySources
-> StandardServletEnvironment#initPropertySources這里并沒有添加因妙。 - getEnvironment().validateRequiredProperties();校驗必須有的環(huán)境變量
6.2 beanFactory = obtainFreshBeanFactory();
- refreshBeanFactory();
- getBeanFactory();
這里返回的是之前創(chuàng)建的DefaultListableBeanFactory
進行BeanFactory的refresh痰憎,在這里會去調用子類的refreshBeanFactory方法,具體子類是怎么刷新的得看子類攀涵,然后再調用子類的getBeanFactory方法铣耘,重新得到一個BeanFactory(AbstractRefreshableApplicationContext#refreshBeanFactory支持重復refresh(),GenericApplicationContext#refreshBeanFactory不支持重復refresh())
6.3 prepareBeanFactory(beanFactory);
- 給當前beanFactory設置一個類加載器以故,用于加載bd的class信息蜗细。
- 設置Spring EL 表達式解析器StandardBeanExpressionResolver
- 為propertyEditorRegistrars添加ResourceEditorRegistrar。PropertyEditor類型轉化器注冊器怒详,用來注冊一些默認的PropertyEditor炉媒。BeanWrapper 本身就是屬性編輯器注冊中心,屬性編輯器作用于beanWrapper內部管理的真實bean注入字段值時昆烁,當某個字段對應的類型 在 BeanWrapper內 有對應的屬性編輯器吊骤,那么對應類型的字段值 就由該屬性編輯器 代理寫入。
- 添加BeanPostProcessor實例:ApplicationContextAwareProcessor静尼,用來執(zhí)行EnvironmentAware白粉、ApplicationEventPublisherAware等回調方法
- 忽略指定類型的依賴:EnvironmentAware、EmbeddedValueResolverAware鼠渺、ResourceLoaderAware鸭巴、ApplicationEventPublisherAware、MessageSourceAware拦盹、ApplicationContextAware鹃祖,統(tǒng)一放在上面的ApplicationContextAwareProcessor里面處理(注意,這個功能僅限于xml的autowire掌敬,@Autowired注解是忽略這個屬性的惯豆,@Autowired依然會注入)
- 添加resolvableDependencies:在byType進行依賴注入時池磁,會先從這個屬性中根據(jù)類型找bean
?1)BeanFactory.class:當前BeanFactory對象
?2)ResourceLoader.class:當前ApplicationContext對象
?3)ApplicationEventPublisher.class:當前ApplicationContext對象
?4)ApplicationContext.class:當前ApplicationContext對象 - 添加BeanPostProcessor實例:ApplicationListenerDetector(初始化后: 判斷當前創(chuàng)建出來的bean實例 是否是 實現(xiàn)了 ApplicationListener 接口的 實例,如果是楷兽,當前bean就是一個 事件監(jiān)聽器 對象地熄,需要把監(jiān)聽者注冊到容器中。)
- 注冊單例bean到單例池:
?1) "environment":StandardEnvironment對象
?2) "systemProperties":System.getProperties()返回的Map對象
?3) "systemEnvironment":System.getenv()返回的Map對象
6.4 postProcessBeanFactory(beanFactory);
留給子類實現(xiàn)
6.5 invokeBeanFactoryPostProcessors(beanFactory);
- 1)執(zhí)行通過ApplicationContext添加進來的BeanDefinitionRegistryPostProcessor的postProcessBeanDefinitionRegistry()方法
- 2)執(zhí)行BeanFactory中實現(xiàn)了PriorityOrdered接口的BeanDefinitionRegistryPostProcessor的postProcessBeanDefinitionRegistry()方法芯杀。
重點:ConfigurationClassPostProcessor的postProcessBeanDefinitionRegistry():
?2-1)拿到beanFactory容器里面注冊的BeanDefinitions端考,這里只能拿到傳入的配置類(這是重點)以及系統(tǒng)自己注冊的那些BeanDefinition(ConfigurationClassPostProcessor、AutowiredAnnotationBeanPostProcessor等)
?2-2)判斷這些BD揭厚,哪些是配置類却特。
Full配置類:@Configuration注解。
Lite配置類:@Configuration注解筛圆,其proxyBeanMethods為false裂明;有注解@Component、@ComponentScan太援、@Import闽晦、@ImportResource;類里面有加了@Bean注解的方法提岔。
?2-3)對配置類進行排序
?2-4)do ... while(!candidates.isEmpty()) 進行循環(huán)解析
?2-4-1)parser.parse(candidates)仙蛉,parser是ConfigurationClassParser
?? A)for循環(huán)解析candidates
?? A-1)this.conditionEvaluator.shouldSkip()處理@Conditional條件注解
?? A-2)do...while(sourceClass != null)處理doProcessConfigurationClass,這里循環(huán)處理父類
?? ?? a)@Component注解碱蒙,處理內部類
?? ?? b)@PropertySource注解荠瘪,屬性配置文件
?? ?? c)@ComponentScan、@ComponentScans會構造掃描器進行掃描赛惩,遍歷掃描得到的BD是否是配置類并進行處理
?? ?? d)@Import(三種情況:ImportSelector哀墓、ImportBeanDefinitionRegistrar、普通的類(直接當作配置類))喷兼,其中DeferredImportSelector麸祷,this.deferredImportSelectorHandler.handle()這里只是存了一下。
?? ?? e)@ImportResource褒搔,導入一個xml配置文件
?? ?? f)@Bean方法
?? ?? g)處理實現(xiàn)的接口里面的@Bean的default方法
?? A-3)this.configurationClasses.put(configClass, configClass)
?? B)this.deferredImportSelectorHandler.process();在本輪配置類解析完之后再執(zhí)行延遲的DeferredImportSelector。
?2-4-2)this.reader.loadBeanDefinitions(configClasses); (生成很多BeanDefinition)將被導入的類@Import以及@Component內部類生成BD注冊到Spring容器中喷面;處理@Bean生成的BD星瘾;處理@ImportResource導入的xml配置文件;處理@Import導入的ImportBeanDefinitionRegistrar
?2-4-3)篩選出新增的BeanDefinition惧辈,并篩選出沒有被解析的配置類繼續(xù)進行處理琳状。@Bean引入的類,其className為null盒齿,會判定其不是配置類念逞。
?Mybatis-Spring 1.3.2版本通過@MapperScan導入了MapperScannerRegistrar類困食,MapperScannerRegistrar類實現(xiàn)了ImportBeanDefinitionRegistrar接口,其registerBeanDefinitions()定義了ClassPathMapperScanner翎承,用來掃描Mapper接口生成BeanDefinition(把BeanClass修改為MapperFactoryBean硕盹,把AutowireMode修改為byTyp)。
?Mybatis-Spring 2.0.6版本MapperScannerRegistrar#registerBeanDefinitions只是注冊了一個新的BD:MapperScannerConfigurer叨咖,掃描邏輯放到了這個類中瘩例,因為這個類是一個BeanDefinitionRegistryPostProcessor。
- 3.)執(zhí)行BeanFactory中實現(xiàn)了Ordered接口的BeanDefinitionRegistryPostProcessor的postProcessBeanDefinitionRegistry()方法
- 4)執(zhí)行BeanFactory中其他的BeanDefinitionRegistryPostProcessor的postProcessBeanDefinitionRegistry()方法
- 5)執(zhí)行上面所有的BeanDefinitionRegistryPostProcessor的postProcessBeanFactory()方法
- 6)執(zhí)行通過ApplicationContext添加進來的BeanFactoryPostProcessor的postProcessBeanFactory()方法
- 7)執(zhí)行BeanFactory中實現(xiàn)了PriorityOrdered接口的BeanFactoryPostProcessor的postProcessBeanFactory()方法
- 8)執(zhí)行BeanFactory中實現(xiàn)了Ordered接口的BeanFactoryPostProcessor的postProcessBeanFactory()方法
- 9)執(zhí)行BeanFactory中其他的BeanFactoryPostProcessor的postProcessBeanFactory()方法
6.6 registerBeanPostProcessors(beanFactory);
- 1.注冊實現(xiàn)PriorityOrdered接口的BeanPostProcessors
- 2.注冊實現(xiàn)Ordered接口的BeanPostProcessors
- 3.注冊普通的BeanPostProcessors
- 4.重新注冊所有MergedBeanDefinitionPostProcessor
- 5.最后再注冊ApplicationListenerDetector
6.7 initMessageSource();
如果BeanFactory中存在一個叫做"messageSource"的BeanDefinition甸各,那么就會把這個Bean對象創(chuàng)建出來并賦值給ApplicationContext的messageSource屬性垛贤,讓ApplicationContext擁有國際化的功能
6.8 initApplicationEventMulticaster();
- this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory); 初始化事件發(fā)布器
6.9 onRefresh();
ServletWebServerApplicationContext#onRefresh
protected void onRefresh() {
super.onRefresh();
try {
createWebServer();
}
catch (Throwable ex) {
throw new ApplicationContextException("Unable to start web server", ex);
}
}
ServletWebServerApplicationContext#createWebServer
- 1)創(chuàng)建webServer
- 2)注冊WebServerGracefulShutdownLifecycle
- 3)注冊WebServerStartStopLifecycle,在finishRefresh()中調用WebServerStartStopLifecycle發(fā)布WebServerInitializedEvent事件趣倾,此時nacos客戶端會監(jiān)聽該事件聘惦,進行服務實例的注冊。
- 4)initPropertySources()屬性源
private void createWebServer() {
WebServer webServer = this.webServer;
ServletContext servletContext = getServletContext();
if (webServer == null && servletContext == null) {
ServletWebServerFactory factory = getWebServerFactory();
this.webServer = factory.getWebServer(getSelfInitializer());
getBeanFactory().registerSingleton("webServerGracefulShutdown",
new WebServerGracefulShutdownLifecycle(this.webServer));
getBeanFactory().registerSingleton("webServerStartStop",
new WebServerStartStopLifecycle(this, this.webServer));
}
else if (servletContext != null) {
try {
getSelfInitializer().onStartup(servletContext);
}
catch (ServletException ex) {
throw new ApplicationContextException("Cannot initialize servlet context", ex);
}
}
initPropertySources();
}
6.10 registerListeners();
將ApplicationListener加入到事件發(fā)布器里面儒恋。
從BeanFactory中獲取ApplicationListener類型的beanName善绎,然后添加到ApplicationContext中的事件廣播器applicationEventMulticaster中去,到這一步因為FactoryBean還沒有調用getObject()方法生成Bean對象碧浊,所以這里要在根據(jù)類型找一下ApplicationListener涂邀,記錄一下對應的beanName
6.11 finishBeanFactoryInitialization(beanFactory);
- 實例化非抽象、非懶加載的單例Bean:getBean(beanName)
- 如果是FactoryBean箱锐,則先獲取FactoryBean實例本身getBean(& + beanName)比勉;
如果FactoryBean是SmartFactoryBean ,并且isEagerInit為true驹止,則提前初始化FactoryBean管理的Bean:getBean(beanName)浩聋。
AbstractBeanFactory#getBean(beanName)
-> AbstractBeanFactory#doGetBean核心流程:
- 1)獲取beanName(別名或者&打頭->去掉&)
- 2)到緩存中獲取共享單實例,單參數(shù)getSingleton臊恋,主要就是從三級緩存中獲取衣洁。
2-1)先從一級緩存查找singletonObjects;
2-2)一級緩存沒有抖仅,且發(fā)生循環(huán)依賴坊夫,則查找二級緩存earlySingletonObjects;
2-3)二級緩存沒有撤卢,則加鎖(先一級环凿、二級查找)從三級緩存查找singletonFactories。
?SmartInstantiationAwareBeanPostProcessor#getEarlyBeanReference()放吩,AOP的AnnotationAwareAspectJAutoProxyCreator和事務的InfrastructureAdvisorAutoProxyCreator都是個SmartInstantiationAwareBeanPostProcessor智听,其getEarlyBeanReference()會調用wrapIfNecessary()創(chuàng)建動態(tài)代理。 - 3)緩存中有對應的數(shù)據(jù),此時緩存數(shù)據(jù)可能是普通單實例 也可能是 FactoryBean到推,所以需要根據(jù)name來進行判斷考赛,并且返回數(shù)據(jù)。
3-1)如果想拿FactoryBean本身對象莉测,則返回該實例颜骤。
3-2)當前bean實例就是普通單實例,則直接返回該實例悔雹。
3-3)當前bean實例是FactoryBean接口實現(xiàn)類复哆,但是本次請求要拿的是FactoryBean實現(xiàn)類內部管理的實例。調用FactoryBean#getObject()腌零。這些對象是沒有經過Bean完整的生命周期的梯找,只是在這里調用了一下初始化后的方法BeanPostProcessor#postProcessAfterInitialization()。 - 4)緩存中沒有bean數(shù)據(jù)益涧,需要創(chuàng)建了
4-1)處理原型循環(huán)依賴
4-2)父容器查找
4-3)獲取合并后的BeanDefinition锈锤,校驗:抽象的BD不能創(chuàng)建實例
4-4)處理depends-on(會先getBean(dep)依賴的bean),如果產生循環(huán)依賴闲询,報錯(依靠兩個Map久免,一個map是 dependentBeanMap 另一個是 dependenciesForBeanMap)
4-5)單例創(chuàng)建,重載getSingleton(beanName, ObjectFactory)扭弧,ObjectFactory -> createBean阎姥,然后還調用getObjectForBeanInstance處理可能是FactoryBean的情況
?A)beforeSingletonCreation(beanName);將當前beanName放入到“正在創(chuàng)建中單實例集合”singletonsCurrentlyInCreation,放入成功鸽捻,說明沒有產生循環(huán)依賴呼巴,失敗,則產生循環(huán)依賴御蒲,里面會拋異常衣赶。這里可以發(fā)現(xiàn)構造方法參數(shù)產生的循環(huán)依賴。
?B)singletonObject = singletonFactory.getObject();這里是創(chuàng)建核心厚满,會調用AbstractAutowireCapableBeanFactory#createBean()府瞄。
??B-1)resolveBeanClass(),如果未加載則使用類加載器將該類加載到JVM中
??B-2)mbdToUse.prepareMethodOverrides();對XML標簽中定義的lookUp屬性進行預處理碘箍,如果只能根據(jù)名字找到一個就標記為非重載的遵馆,這樣在后續(xù)就不需要去推斷到底是哪個方法了,對于@LookUp注解標注的方法是不需要在這里處理的丰榴,AutowiredAnnotationBeanPostProcessor會處理這個注解
??B-3)resolveBeforeInstantiation()短路操作团搞。InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation。如果不為null多艇,經過BeanPostProcessor#postProcessAfterInitialization()后會直接返回。
??B-4)doCreateBean()核心方法:創(chuàng)建bean實例對象像吻,并且生命周期的動作大部分都在這里峻黍。
?C)afterSingletonCreation(beanName);從singletonsCurrentlyInCreation移除
?D)addSingleton(beanName, singletonObject);將實例bean加入到一級緩存复隆,從二級、三級緩存移除姆涩。
4-6)原型創(chuàng)建
4-7)其他情況實例創(chuàng)建 - 5)創(chuàng)建的實例是否與requiredType類型相匹配
- 6)返回實例
著重看一下AbstractAutowireCapableBeanFactory#doCreateBean主流程:
- 1)createBeanInstance()挽拂,創(chuàng)建出真實的bean實例,并且將其包裝到BeanWrapper實例中骨饿。
?1-1)InstanceSupplier創(chuàng)建實例
?1-2)instantiateUsingFactoryMethod()亏栈,工廠方法創(chuàng)建實例,分為靜態(tài)工廠方法跟實例工廠方法
??step1.新建一個BeanWrapper宏赘,并對這個BeanWrapper做了初始化
??step2.明確了實例化當前這個Bean到底是靜態(tài)工廠還是實例工廠(factoryBeanName 不為空)
??step3.從緩存(原型模式有用)绒北、類中獲取對應了方法以及參數(shù)(篩選出所有候選方法并排序: 優(yōu)先級:public > 非public,參數(shù)多 > 參數(shù)少)
??step4.明確了方法需要的最小的參數(shù)數(shù)量并對配置文件中的標簽屬性進行了一次解析察署,然后從解析出來的參數(shù)中查找當前的這個候選方法需要的參數(shù)或者自動注入
??step5.計算類型差異(首先判斷bd中是寬松模式還是嚴格模式闷游,目前看來只有@Bean標注的方法解析得到的Bean會使用嚴格模式來計算類型差異,其余都是使用寬松模式)贴汪,篩選出差異最小的方法
??step6.對推斷出來的方法做驗證(不能為null脐往,方法不能有多個,返回值不能為void)
??step7.反射調用對應方法進行實例化
?1-3)構造方法以及解析過扳埂,如果構造方法需要自動注入?yún)?shù)业簿,則調用autowireConstructor(beanName, mbd, null, null),否則無參構造方法處理instantiateBean(beanName, mbd)阳懂。
?1-4)ctors = determineConstructorsFromBeanPostProcessors()梅尤,典型的應用:@Autowired 注解打在了 構造器方法上。參考@Autowired AutowiredAnnotationBeanPostProcessor
?1-5)條件一:ctors不為null:說明存在1個或多個@Autowired標注的方法希太。條件二:autowiredMode為AUTOWIRE_CONSTRUCTOR 克饶。條件三:配置文件中,bean信息配置了 構造參數(shù)信息誊辉。條件四:getBean時矾湃,args有參數(shù)。這四個條件任意一個成立堕澄,則調用autowireConstructor(beanName, mbd, ctors, args)邀跃,選擇一個差異值最小的,參數(shù)最長的構造函數(shù)
?1-6)有偏好選用的構造方法 mbd.getPreferredConstructors()蛙紫,調用autowireConstructor(beanName, mbd, ctors, null);
?1-7)instantiateBean(beanName, mbd);未指定構造參數(shù)拍屑,未設定偏好...使用默認的 無參數(shù)的構造方法進行創(chuàng)建實例 - 2)applyMergedBeanDefinitionPostProcessors(),MergedBeanDefinitionPostProcessor#postProcessMergedBeanDefinition()坑傅。
?2-1)AutowiredAnnotationBeanPostProcessor會提取注入點:提取出來當前beanType類型整個繼承體系內的 @Autowired @Value @Inject 信息 并且包裝成一個InjectionMetadata的一個對象僵驰,存放到 AutowiredAnnotationBeanPostProcessor 它的緩存中了,key是 beanName。 - 3)循環(huán)依賴的相關操作:addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
?getEarlyBeanReference()會調用SmartInstantiationAwareBeanPostProcessor#getEarlyBeanReference() - 4)populateBean()蒜茴,依賴注入
?4-1)InstantiationAwareBeanPostProcessor#postProcessAfterInstantiation()
?4-2)autowireMode為AUTOWIRE_BY_NAME時星爪,autowireByName();autowireMode為AUTOWIRE_BY_TYPE時粉私,autowireByType()顽腾。
?autowireByName(),首先找到需要進行依賴注入的屬性名诺核,有setter方法抄肖,不是簡單類型(基本數(shù)據(jù)類型、枚舉窖杀、日期等)漓摩,然后直接調用getBean(propertyName)獲取實例進行依賴注入。
?autowireByType()陈瘦,首先找到需要進行依賴注入的屬性名幌甘,有setter方法,不是簡單類型(基本數(shù)據(jù)類型痊项、枚舉锅风、日期等),然后調用resolveDependency()解析依賴鞍泉。
??step1.通過依賴類型查詢到所有的類型匹配的bean的名稱
??step2.如果找到了多個的話皱埠,再根據(jù)依賴的名稱匹配對應的Bean的名稱
??step3.調用getBean得到這個需要被注入的Bean
??step4.最后反射調用字段的set方法完成屬性注入
?4-3)InstantiationAwareBeanPostProcessor#postProcessProperties,屬性注入咖驮,典型應用:@Autowired 注解的注入(AutowiredAnnotationBeanPostProcessor )边器。
?4-4)對需要進行依賴檢查的屬性進行依賴檢查checkDependencies()
?4-5)將依賴注入合并后的pvs 應用到 真實的Bean實例中。applyPropertyValues()托修,屬性來源:XML配置忘巧,byName自動注入的,byType自動注入的睦刃。 - 5)initializeBean()砚嘴,調用初始化方法
?5-1)invokeAwareMethods(beanName, bean),BeanNameAware涩拙、BeanClassLoaderAware和BeanFactoryAware處理际长。
?5-2)applyBeanPostProcessorsBeforeInitialization(),BeanPostProcessor#postProcessBeforeInitialization()
?5-3)invokeInitMethods()兴泥,首先調用InitializingBean#afterPropertiesSet()工育,如果沒有實現(xiàn)接口,則可invokeCustomInitMethod()調用init-method定義的方法
?5-4)applyBeanPostProcessorsAfterInitialization()搓彻,BeanPostProcessor#postProcessAfterInitialization()
??AOP功能實現(xiàn)AnnotationAwareAspectJAutoProxyCreator(@EnableAspectJAutoProxy注解或者<aop:aspectj-autoproxy />引入)是個BeanPostProcessor如绸。其postProcessAfterInitialization()會調用wrapIfNecessary()創(chuàng)建動態(tài)代理嘱朽。
??事務功能實現(xiàn)InfrastructureAdvisorAutoProxyCreator(@EnableTransactionManagement注解或者<tx:annotation-driven>引入)是個BeanPostProcessor。其postProcessAfterInitialization()會調用wrapIfNecessary()創(chuàng)建動態(tài)代理怔接。 - 6)循環(huán)依賴相關處理
- 7)注冊銷毀方法
6.12 finishRefresh();
- initLifecycleProcessor();設置this.lifecycleProcessor為DefaultLifecycleProcessor
- getLifecycleProcessor().onRefresh();
autoStartupOnly為true:表示只啟動 SmartLifecycle 生命周期對象燥翅,為false表示全部啟動,包括普通的Lifecycle蜕提。
根據(jù)phase值,對SmartLifecycle 對象分組靶端,值越小谎势,越先啟動。
?nacos 客戶端jar包引入的自動配置類NacosServiceRegistryAutoConfiguration注入NacosAutoServiceRegistration杨名,NacosAutoServiceRegistration是個ApplicationListener脏榆,監(jiān)聽WebServerInitializedEvent事件。WebServerStartStopLifecycle是個SmartLifecycle台谍,在refresh()的最后會調用其start()方法须喂,會發(fā)布ServletWebServerInitializedEvent事件。此時NacosAutoServiceRegistration#onApplicationEvent就會被調用趁蕊,進行服務實例注冊坞生。 - 發(fā)布ContextRefreshedEvent事件
7.SpringApplication#run:后置處理
- 13.發(fā)布ApplicationStartedEvent事件,表示Spring容器已經啟動
- 14.從Spring容器中獲取ApplicationRunner和CommandLineRunner掷伙,并執(zhí)行其run()
- 15.發(fā)布ApplicationReadyEvent事件是己,表示Spring容器已經準備好了