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)建完成放入一級緩存