1 注解
Retention
使用了注解@Retention的類, RUNTIME 注解信息會(huì)加載到JVM中,可以反射性讀取,默認(rèn)是CLASS
@Inherited
1、在類繼承關(guān)系中,子類會(huì)繼承父類使用的注解中被@Inherited修飾的注解
2、在接口繼承關(guān)系中,子接口不會(huì)繼承父接口中的任何注解,不管父接口中使用的注解有沒有被@Inherited修飾
3、類實(shí)現(xiàn)接口時(shí),不會(huì)繼承任何接口中定義的注解
先執(zhí)行@ ComponentScan parse,EnableAutoConfigurationImportSelector processDeferredImportSelectors,再執(zhí)行@ AutoConfigurationPackages.Registrar
@EnableAutoConfiguration
Run -> refreshcontext->Refresh -> 執(zhí)行 invokeBeanFactoryPostProcessors
@AutoConfigurationPackage -> @Import(AutoConfigurationPackages.Registrar.class)
而Registrar類作用是掃描主配置類同級目錄以及子包,并將相應(yīng)的組件導(dǎo)入到springboot創(chuàng)建管理的容器中;
@Import(EnableAutoConfigurationImportSelector.class)
selectImports方法執(zhí)行的過程中,會(huì)使用內(nèi)部工具類SpringFactoriesLoader,查找classpath上所有jar包中的META-INF/spring.factories進(jìn)行加載,實(shí)現(xiàn)將配置類信息交給SpringFactory加載器進(jìn)行一系列的容器創(chuàng)建過程
@ComponentScan
Run -> refreshcontext->Refresh -> 執(zhí)行 invokeBeanFactoryPostProcessors
@Repeatable 注解是用于聲明其它類型注解的元注解,來表示這個(gè)聲明的注解是可重復(fù)的。
@Repeatable的值是另一個(gè)注解,其可以通過這個(gè)另一個(gè)注解的值來包含這個(gè)可重復(fù)的注解。
@ComponentScan注解主要是從約定的掃描路徑中,識別標(biāo)注了組件注冊注解的類,并且把這些類自動(dòng)注冊到spring IoC容器中,這些類就是我們通常所言的bean。
@ComponentScan 如果不設(shè)置value屬性,默認(rèn)掃描路徑是啟動(dòng)類
@ComponentScan(excludeFilters = {
@Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
AutoConfigurationExcludeFilter 的作用是過濾掉會(huì)自動(dòng)配置的配置類,避免重復(fù)
TypeExcludeFilter 的作用是加載spring bean池中所有針對TypeExcludeFilter的擴(kuò)展,并循環(huán)遍歷這些擴(kuò)展類調(diào)用其match方法
2 兩種啟動(dòng)方式
1 SpringBootServletInitializer實(shí)現(xiàn)了tomcat預(yù)留的ServletContainerInitializer的onStartup接口,通過tomcat啟動(dòng)實(shí)現(xiàn)boot項(xiàng)目啟動(dòng)
2 Springboot啟動(dòng)時(shí),會(huì)調(diào)用內(nèi)嵌tomcat的啟動(dòng),自己創(chuàng)建web容器
onRefresh -> createEmbeddedServletContainer->
3 SpringApplication初始化
setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
4 SpringApplication run
Step 1 getRunListeners
SpringApplicationRunListeners listeners = getRunListeners(args);
在SpringApplicationRunListener的實(shí)現(xiàn)類 EventPublishingRunListener實(shí)例化時(shí),將SpringApplication的ApplicationListener實(shí)例裝載到EventPublishingRunListener對象里
listeners.starting() 觸發(fā)ApplicationStartedEvent
Step 2 prepareEnvironment
getOrCreateEnvironment()
AbstractEnvironment初始化 頂層父
->StandardServletEnvironment(customizePropertySources方法 ) 子
->StandardEnvironment(customizePropertySources方法 中間父,
增加systemProperties對應(yīng)java環(huán)境, systemEnvironment對應(yīng)系統(tǒng)環(huán)境變量)
listeners.environmentPrepared 觸發(fā) ApplicationEnvironmentPreparedEvent
5 環(huán)境構(gòu)建->監(jiān)聽器
getApplicationListeners(event, type) 根據(jù)不同的事件類型獲取不同的監(jiān)聽器,并觸發(fā)監(jiān)聽
1)
ApplicationStartedEvent
0 = {LoggingApplicationListener@2248}
1 = {BackgroundPreinitializer@2249}
2 = {DelegatingApplicationListener@2250}
3 = {LiquibaseServiceLocatorApplicationListener@2251}
2)
ApplicationEnvironmentPreparedEvent
0 = {ConfigFileApplicationListener@2405}
1 = {AnsiOutputApplicationListener@2406}
2 = {LoggingApplicationListener@2407}
3 = {ClasspathLoggingApplicationListener@2408}
4 = {BackgroundPreinitializer@2409}
5 = {DelegatingApplicationListener@2410}
6 = {FileEncodingApplicationListener@2411}
5.1 LoggingApplicationListener
private void onApplicationStartingEvent(ApplicationStartingEvent event) {
this.loggingSystem = LoggingSystem
.get(event.getSpringApplication().getClassLoader());
this.loggingSystem.beforeInitialize();
}
LoggingSystem
Map<String, String> systems = new LinkedHashMap<String, String>();
systems.put("ch.qos.logback.core.Appender",
"org.springframework.boot.logging.logback.LogbackLoggingSystem");
systems.put("org.apache.logging.log4j.core.impl.Log4jContextFactory",
"org.springframework.boot.logging.log4j2.Log4J2LoggingSystem");
systems.put("java.util.logging.LogManager",
"org.springframework.boot.logging.java.JavaLoggingSystem");
SYSTEMS = Collections.unmodifiableMap(systems);
public static LoggingSystem get(ClassLoader classLoader) {
…
for (Map.Entry<String, String> entry : SYSTEMS.entrySet()) {
if (ClassUtils.isPresent(entry.getKey(), classLoader)) {
return get(classLoader, entry.getValue());
}
}
}
5.2 ConfigFileApplicationListener
在執(zhí)行處理器時(shí),會(huì)加載屬性文件
org.springframework.boot.env.EnvironmentPostProcessor=\
org.springframework.boot.cloud.CloudFoundryVcapEnvironmentPostProcessor,\
org.springframework.boot.env.SpringApplicationJsonEnvironmentPostProcessor
List<EnvironmentPostProcessor> postProcessors = loadPostProcessors();
postProcessors.add(this);
將ConfigFileApplicationListener加入到postProcessors中
ConfigFileApplicationListener主要用來處理項(xiàng)目配置。項(xiàng)目中的 properties 和yml文件都是其內(nèi)部類所加載。具體來看一下:
public void postProcessEnvironment(ConfigurableEnvironment environment,
SpringApplication application) {
addPropertySources(environment, application.getResourceLoader());
configureIgnoreBeanInfo(environment);
bindToSpringApplication(environment, application);
}
addPropertySources遍歷各個(gè)路徑下帶yaml、properties、yml后綴的的文件,并加載
PropertySourcesLoader初始化,加載PropertySourceLoader對應(yīng)的類
org.springframework.boot.env.PropertySourceLoader=\
org.springframework.boot.env.PropertiesPropertySourceLoader,\
org.springframework.boot.env.YamlPropertySourceLoader
DEFAULT_SEARCH_LOCATIONS = "classpath:/,classpath:/config/,file:./,file:./config/"
2 = "file:./"
3 = "file:./config/"
0 = "classpath:/"
1 = "classpath:/config/"
org.yaml.snakeyaml.Yaml
6 創(chuàng)建Spring容器
createApplicationContext
org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext
AnnotationConfigEmbeddedWebApplicationContext
public AnnotationConfigEmbeddedWebApplicationContext() {
//獲取spring的內(nèi)置處理器
this.reader = new AnnotatedBeanDefinitionReader(this);
//獲取spring的類掃描器Component
this.scanner = new ClassPathBeanDefinitionScanner(this);
}
AnnotatedBeanDefinitionReader解析器用來解析帶注解的bean
ClassPathBeanDefinitionScanner 提供了包掃描路徑的方式啟動(dòng)容器
AnnotatedBeanDefinitionReader實(shí)例化
觸發(fā)AnnotationConfigUtils .registerAnnotationConfigProcessors
將spring寫死的那幾個(gè)基礎(chǔ)設(shè)施類封裝成BeanDefinition放到容器當(dāng)中
注冊了實(shí)現(xiàn)Order接口的排序器 AnnotationAwareOrderComparator
設(shè)置@AutoWired的候選的解析器 ContextAnnotationAutowireCandidateResolver
注冊解析我們配置類的后置處理器 ConfigurationClassPostProcessor
注冊處理@Autowired 注解的處理器 AutowiredAnnotationBeanPostProcessor
注冊處理@Required屬性的注解處理器 RequiredAnnotationBeanPostProcessor
注冊處理JSR規(guī)范的注解處理器 CommonAnnotationBeanPostProcessor
處理jpa注解的處理器 PersistenceAnnotationBeanPostProcessor
處理監(jiān)聽方法的注解解析器 EventListenerMethodProcessor
注冊事件監(jiān)聽器工廠 DefaultEventListenerFactory
ClassPathBeanDefinitionScanner實(shí)例化
觸發(fā)registerDefaultFilters
裝載@Component @ManagedBean(Java EE 6) @Named(JSR-330)這些注解的過濾規(guī)則
this.includeFilters.add(new AnnotationTypeFilter(Component.class))
javax.annotation.ManagedBean
javax.inject.Named
7 Spring容器前置處理
prepareContext
7.1 applyInitializers
執(zhí)行容器中的ApplicationContextInitializer
DelegatingApplicationContextInitializer
提供了一個(gè)屬性key(context.initializer.classes)在配置文件中配置自定義的初始化器實(shí)現(xiàn)類
ContextIdApplicationContextInitializer
ConfigurationWarningsApplicationContextInitializer
用來報(bào)告Spring容器的一些常見的錯(cuò)誤配置的
內(nèi)部包含ConfigurationWarningsPostProcessor、ComponentScanPackageCheck兩個(gè)內(nèi)部靜態(tài)類
ConfigurationWarningsPostProcessor ->BeanDefinitionRegistryPostProcessor->
BeanFactoryPostProcessor
BeanFactoryPostProcessor接口:允許對spring容器的bean definition進(jìn)行自定義的修改, 實(shí)現(xiàn)了BeanFactoryPostProcessor接口的Bean,會(huì)在創(chuàng)建其他Bean之前首先執(zhí)行該實(shí)現(xiàn)接口
ConfigurationWarningsPostProcessor.postProcessBeanDefinitionRegistry 把注冊BeanDefinition實(shí)例過程中產(chǎn)生的告警信息傳給check實(shí)例輸出告警,從現(xiàn)有的beanDefinition中取出是AnnotatedBeanDefinition類型的(也就是支持注解信息讀取的),將beanDefinition的ComponentScan里設(shè)置的包放入待過濾的包集合里,目前僅僅針對org和org.springframework包,
ServerPortInfoApplicationContextInitializer
SharedMetadataReaderFactoryContextInitializer
生產(chǎn)SharedMetadataReaderFactoryBean,并同時(shí)產(chǎn)生一個(gè)MetadataReader用于讀取類的元數(shù)據(jù),然后從容器獲取了名為internalConfigurationAnnotationProcessor的BeanDefinition,把上面生成的metadataReaderFactory設(shè)置到它的屬性中,后續(xù)BeanDefinitionReader在完成spring掃描時(shí)就會(huì)用它來完成一些Bean的元數(shù)據(jù)解析
AutoConfigurationReportLoggingInitializer
7.2 Load
加載我們啟動(dòng)類,將啟動(dòng)類注入容器
this.annotatedReader.register(source);
以注解的方式,將啟動(dòng)類bean信息存入beanDefinitionMap
public void registerBean(Class<?> annotatedClass, String name, Class<? extends Annotation>... qualifiers) {
AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(annotatedClass);
if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) {
return;
}
//解析 @Scope 注解 默認(rèn)為單例(singleton)
ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);
abd.setScope(scopeMetadata.getScopeName());
//生成 beanName 獲取啟動(dòng)類注解、子注解以及注解中所有的屬性值,判斷注解是否包含
org.springframework.stereotype.Component并且屬性值存在value的,如果存在則取value值
作為beanName,否則根據(jù)類名生成beanName
String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry));
// 解析注解:@LazyInit、@Primary、@dependsOn、@role、@description
AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);
…
//把 BeanDefinition 包裝為 BeanDefinitionHolder,包含 BeanDefinition,beanName,aliasName
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);
// 解析代理模型
definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
//將 BeanDefinition 注冊到 BeanFactory
BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
}
contextLoaded通知監(jiān)聽器,容器已準(zhǔn)備就緒
觸發(fā)ApplicationPreparedEvent事件
ConfigFileApplicationListener 增加PropertySourceOrderingPostProcessor
LoggingApplicationListener
BackgroundPreinitializer 預(yù)初始化
DelegatingApplicationListener 擴(kuò)展點(diǎn) context.listener.classes
8 refreshContext刷新容器
執(zhí)行到這里,springBoot相關(guān)的處理工作已經(jīng)結(jié)束,接下的工作就交給了spring
prepareRefresh 在容器初始化前,做一些簡單記錄工作,同時(shí)初始一個(gè)容器所需的屬性
8.1 obtainFreshBeanFactory
refreshBeanFactory()-> GenericApplicationContext. refreshBeanFactory,使用 CAS 改變 refreshed 標(biāo)記,再給 BeanFactory 設(shè)置一個(gè)序列化 ID。
getBeanFactory() 獲取早已實(shí)例化的beanFactory
8.2 prepareBeanFactory
初始化一些組件,添加到BeanFactory 中
添加一個(gè)名為 ApplicationContextAwareProcessor 的 Bean 的后置處理器,是對spring中實(shí)現(xiàn)自Aware接口的bean等進(jìn)行后置處理,ignoredDependencyInterfaces主要是緩存需要在bean進(jìn)行屬性注入時(shí)需要忽略的接口
添加一個(gè) ApplicationListenerDetector 的 BeanPostProcessor,用于解析實(shí)現(xiàn)了ApplicationListener接口的bean
如果包含 loadTimeWeaver,則添加一個(gè) LoadTimeWeaverAwareProcessor 的 BeanPostProcessor,與 AOP 有關(guān),針對LoadTimeWeaverAware類型的bean設(shè)置LoadTimeWeaver,實(shí)現(xiàn)LoadTimeWeaverAware接口的類只有AspectJWeavingEnabler。
注冊默認(rèn)需要的 bean,environment、systemProperties、systemEnvironment
8.3 invokeBeanFactoryPostProcessors
調(diào)用 BeanFactoryPostProcessors(Bean工廠后置處理器)
先調(diào)用實(shí)現(xiàn)了 BeanDefinitionRegistryPostProcessor 接口里的方法,保證所有 Bean 已注冊到容器中,后調(diào)用實(shí)現(xiàn)了 BeanFactoryPostProcessor 接口里的方法,對 BeanFactory 進(jìn)行修改,同時(shí),BeanFactory 后置處理器是有調(diào)用順序。
這里是 Spring 很重要的一個(gè)擴(kuò)展點(diǎn)。通過配置配置的 Bean 都會(huì)被注冊都容器中,同時(shí)程序員配置的 BeanFactory 后置處理器或是在 BeanFactory 后置處理器添加的后置處理器都會(huì)在這里執(zhí)行。動(dòng)態(tài)注冊 BeanDefinition 是在這里完成的,同時(shí)程序員也可以實(shí)現(xiàn)相關(guān)接口在這里對已注冊 BeanDefinition 進(jìn)行修改。
postProcessBeanDefinitionRegistry->BeanFactoryPostProcessor
代碼解讀:
入?yún)eanFactoryPostProcessors 已經(jīng)注冊的BeanFactoryPostProcessor 0{ConfigurationWarningsApplicationContextInitializer$ConfigurationWarningsPostProcessor@3691}
1{SharedMetadataReaderFactoryContextInitializer$CachingMetadataReaderFactoryPostProcessor@3692}
2{ConfigFileApplicationListener$PropertySourceOrderingPostProcessor@3693}
步驟:
1上面已注冊的并且實(shí)現(xiàn)了BeanDefinitionRegistryPostProcessor的0和1,執(zhí)行postProcessBeanDefinitionRegistry
2 獲取實(shí)現(xiàn)了BeanDefinitionRegistryPostProcessor的并且實(shí)現(xiàn)了PriorityOrdered的,
執(zhí)行postProcessBeanDefinitionRegistry
3 獲取實(shí)現(xiàn)了BeanDefinitionRegistryPostProcessor的并且實(shí)現(xiàn)了Ordered的,
執(zhí)行postProcessBeanDefinitionRegistry
4獲取實(shí)現(xiàn)了BeanDefinitionRegistryPostProcessor的剩下的,執(zhí)行postProcessBeanDefinitionRegistry
5 將1-4中涉及的實(shí)現(xiàn)了BeanDefinitionRegistryPostProcessor(也就是BeanFactoryPostProcessor)的后置處理器
執(zhí)行invokeBeanFactoryPostProcessors->postProcessBeanFactory
6獲取實(shí)現(xiàn)了BeanFactoryPostProcessor,過濾掉上面已經(jīng)執(zhí)行過的,按照實(shí)現(xiàn)了PriorityOrdered接口、實(shí)現(xiàn)了
Ordered接口、剩余的優(yōu)先級,執(zhí)行postProcessBeanFactory
8.3.1 ConfigurationClassPostProcessor
重要的 BeanFactory 后置處理器,解析用戶提供的 Bean
postProcessBeanDefinitionRegistry
this.beanDefinitionNames
0 = "org.springframework.context.annotation.internalConfigurationAnnotationProcessor"
1 = "org.springframework.context.annotation.internalAutowiredAnnotationProcessor"
2 = "org.springframework.context.annotation.internalRequiredAnnotationProcessor"
3 = "org.springframework.context.annotation.internalCommonAnnotationProcessor"
4 = "org.springframework.context.event.internalEventListenerProcessor"
5 = "org.springframework.context.event.internalEventListenerFactory"
6 = "adminApplicationBootstrap"
7 = "org.springframework.boot.autoconfigure.internalCachingMetadataReaderFactory"
checkConfigurationClassCandidate根據(jù)類上的注解判斷配置類是FULL模式還是LITE模式
包含注解@Configuration,定義為full
包含注解@Component @ComponentScan @Import @ImportResource,定義為lite
Full lite作為是否加載過的標(biāo)志
解析配置類
ConfigurationClassParser. Parse->processConfigurationClass->doProcessConfigurationClass
// 把前面解析為 ConfigurationClass 類解析為 BeanDefinition 加入到 BeanDefinitionMap
this.reader.loadBeanDefinitions(configClasses);
8.4 registerBeanPostProcessors
實(shí)例化 Bean準(zhǔn)備
spring 先添加 Bean 后置處理器 BeanPostProcessor,因?yàn)?BeanPostProcessor 會(huì)在實(shí)例化 Bean 使用
postProcessorNames = {String[14]@4479}
0 = "org.springframework.context.annotation.internalAutowiredAnnotationProcessor"
1 = "org.springframework.context.annotation.internalRequiredAnnotationProcessor"
2 = "org.springframework.context.annotation.internalCommonAnnotationProcessor"
3 = "org.springframework.boot.context.properties.ConfigurationPropertiesBindingPostProcessor"
4 = "embeddedServletContainerCustomizerBeanPostProcessor"
5 = "errorPageRegistrarBeanPostProcessor"
6 = "vn.com.vng.wpl.kafka.config.internalKafkaListenerAnnotationProcessor"
7 = "org.springframework.aop.config.internalAutoProxyCreator"
8 = "processor"
9 = "scmValueAnnotationBeanPostProcessor"
10 = "methodValidationPostProcessor"
11 = "dataSourceInitializerPostProcessor"
12 = "persistenceExceptionTranslationPostProcessor"
13 = "org.springframework.jms.config.internalJmsListenerAnnotationProcessor"
beanFactory按照優(yōu)先級分批實(shí)例化上面的14個(gè)beanPostProcessor,然后注冊進(jìn)來,并且實(shí)例化注冊
BeanPostProcessorChecker、ApplicationListenerDetector
8.5 finishBeanFactoryInitialization
8.5.1 實(shí)例化Bean
instanceWrapper = createBeanInstance(beanName, mbd, args);之后,會(huì)返回一個(gè)實(shí)例化對象,但這個(gè)對象并不是一個(gè)完整的 Bean,Spring 在這之后調(diào)用 populateBean 方法完成屬性注入。
8.5.2 populateBean
調(diào)用 Bean 后置處理器的 postProcessProperties 方法
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);、
觸發(fā)了
AutowiredAnnotationBeanPostProcessor. postProcessPropertyValues處理 @Autowired 注解
8.5.3 applyPropertyValues
上面只是將屬性保存了起來,并未真正設(shè)置到 bean 中,這里設(shè)置到 bean 中
8.5.4 循環(huán)依賴
Spring中做三級緩存的三個(gè)容器:
一級緩存:singletonObjects,二級緩存:earlySingletonObjects,三級緩存:singletonFactories
入口: beanFactory.preInstantiateSingletons()
->DefaultListableBeanFactory. preInstantiateSingletons
->AbstractBeanFactory. doGetBean
->Object sharedInstance = getSingleton(beanName);
按順序從1-3級緩存取bean,若從三級緩存取到,那么三級緩存->二級緩存
->public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory)
此處是未能從三級緩存取到的,則要通過實(shí)例化獲取
->DefaultSingletonBeanRegistry. beforeSingletonCreation
->this.singletonsCurrentlyInCreation.add(beanName)
->AbstractBeanFactory. getObject
-> AbstractAutowireCapableBeanFactory .createBean(beanName, mbd, args)
-> instanceWrapper = createBeanInstance(beanName, mbd, args);
-> addSingletonFactory
-> this.singletonFactories.put(beanName, singletonFactory);
Bean實(shí)例化完成但是未完成bean屬性注入的,放三級緩存
-> populateBean
-> afterSingletonCreation
-> this.singletonsCurrentlyInCreation.remove(beanName)
-> addSingleton
-> this.singletonObjects.put(beanName, singletonObject);
Bean創(chuàng)建完成放入一級緩存
浙公網(wǎng)安備 33010602011771號