1 注解

Retention

使用了注解@Retention的类, RUNTIME 注解信息会加载到JVM中,可以反射性读取,默认是CLASS

 

@Inherited

1、在类继承关系中,子类会继承父类使用的注解中被@Inherited修饰的注解

2、在接口继承关系中,子接口不会继承父接口中的任何注解,不管父接口中使用的注解有没有被@Inherited修饰

3、类实现接口时,不会继承任何接口中定义的注解

先执行@ ComponentScan parse,EnableAutoConfigurationImportSelector processDeferredImportSelectors,再执行@ AutoConfigurationPackages.Registrar

 

 

@EnableAutoConfiguration

Run -> refreshcontext->Refresh -> 执行 invokeBeanFactoryPostProcessors

@AutoConfigurationPackage -> @Import(AutoConfigurationPackages.Registrar.class)  

而Registrar类作用是扫描主配置类同级目录以及子包,并将相应的组件导入到springboot创建管理的容器中;

@Import(EnableAutoConfigurationImportSelector.class)

selectImports方法执行的过程中,会使用内部工具类SpringFactoriesLoader,查找classpath上所有jar包中的META-INF/spring.factories进行加载,实现将配置类信息交给SpringFactory加载器进行一系列的容器创建过程

 

@ComponentScan

Run -> refreshcontext->Refresh -> 执行 invokeBeanFactoryPostProcessors

@Repeatable 注解是用于声明其它类型注解的元注解,来表示这个声明的注解是可重复的。
@Repeatable的值是另一个注解,其可以通过这个另一个注解的值来包含这个可重复的注解。

@ComponentScan注解主要是从约定的扫描路径中,识别标注了组件注册注解的类,并且把这些类自动注册到spring IoC容器中,这些类就是我们通常所言的bean。

@ComponentScan 如果不设置value属性,默认扫描路径是启动类

@ComponentScan(excludeFilters = {

              @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),

              @Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })

AutoConfigurationExcludeFilter 的作用是过滤掉会自动配置的配置类,避免重复

TypeExcludeFilter 的作用是加载spring bean池中所有针对TypeExcludeFilter的扩展,并循环遍历这些扩展类调用其match方法

 

2 两种启动方式

1 SpringBootServletInitializer实现了tomcat预留的ServletContainerInitializer的onStartup接口,通过tomcat启动实现boot项目启动

2 Springboot启动时,会调用内嵌tomcat的启动,自己创建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的实现类 EventPublishingRunListener实例化时,将SpringApplication的ApplicationListener实例装载到EventPublishingRunListener对象里

 

listeners.starting() 触发ApplicationStartedEvent

 

Step 2 prepareEnvironment

getOrCreateEnvironment()

AbstractEnvironment初始化 顶层父

->StandardServletEnvironment(customizePropertySources方法 ) 子

->StandardEnvironment(customizePropertySources方法 中间父,    

增加systemProperties对应java环境, systemEnvironment对应系统环境变量)

 

listeners.environmentPrepared 触发 ApplicationEnvironmentPreparedEvent

 

5 环境构建->监听器

getApplicationListeners(event, type) 根据不同的事件类型获取不同的监听器,并触发监听

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

在执行处理器时,会加载属性文件

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主要用来处理项目配置。项目中的 properties 和yml文件都是其内部类所加载。具体来看一下:

     public void postProcessEnvironment(ConfigurableEnvironment environment,

                       SpringApplication application) {

              addPropertySources(environment, application.getResourceLoader());

              configureIgnoreBeanInfo(environment);

              bindToSpringApplication(environment, application);

     }

addPropertySources遍历各个路径下带yaml、properties、yml后缀的的文件,并加载

PropertySourcesLoader初始化,加载PropertySourceLoader对应的类

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 创建Spring容器

createApplicationContext

org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext

AnnotationConfigEmbeddedWebApplicationContext

public AnnotationConfigEmbeddedWebApplicationContext() {

         //获取spring的内置处理器

         this.reader = new AnnotatedBeanDefinitionReader(this);

         //获取spring的类扫描器Component

         this.scanner = new ClassPathBeanDefinitionScanner(this);

}

     AnnotatedBeanDefinitionReader解析器用来解析带注解的bean

ClassPathBeanDefinitionScanner 提供了包扫描路径的方式启动容器

 

AnnotatedBeanDefinitionReader实例化

触发AnnotationConfigUtils .registerAnnotationConfigProcessors

将spring写死的那几个基础设施类封装成BeanDefinition放到容器当中

注册了实现Order接口的排序器              AnnotationAwareOrderComparator

设置@AutoWired的候选的解析器            ContextAnnotationAutowireCandidateResolver

注册解析我们配置类的后置处理器           ConfigurationClassPostProcessor

注册处理@Autowired 注解的处理器           AutowiredAnnotationBeanPostProcessor

注册处理@Required属性的注解处理器      RequiredAnnotationBeanPostProcessor

注册处理JSR规范的注解处理器                    CommonAnnotationBeanPostProcessor

处理jpa注解的处理器                                PersistenceAnnotationBeanPostProcessor

处理监听方法的注解解析器                            EventListenerMethodProcessor

注册事件监听器工厂                                          DefaultEventListenerFactory

 

ClassPathBeanDefinitionScanner实例化

触发registerDefaultFilters

装载@Component @ManagedBean(Java EE 6) @Named(JSR-330)这些注解的过滤规则

        this.includeFilters.add(new AnnotationTypeFilter(Component.class))           

                                                 javax.annotation.ManagedBean

                                            javax.inject.Named

 

7 Spring容器前置处理

prepareContext

 

7.1 applyInitializers

执行容器中的ApplicationContextInitializer

DelegatingApplicationContextInitializer

提供了一个属性key(context.initializer.classes)在配置文件中配置自定义的初始化器实现类

 

ContextIdApplicationContextInitializer

 

ConfigurationWarningsApplicationContextInitializer

用来报告Spring容器的一些常见的错误配置的

内部包含ConfigurationWarningsPostProcessor、ComponentScanPackageCheck两个内部静态类

ConfigurationWarningsPostProcessor ->BeanDefinitionRegistryPostProcessor->

BeanFactoryPostProcessor

BeanFactoryPostProcessor接口:允许对spring容器的bean definition进行自定义的修改, 实现了BeanFactoryPostProcessor接口的Bean,会在创建其他Bean之前首先执行该实现接口

ConfigurationWarningsPostProcessor.postProcessBeanDefinitionRegistry 把注册BeanDefinition实例过程中产生的告警信息传给check实例输出告警,从现有的beanDefinition中取出是AnnotatedBeanDefinition类型的(也就是支持注解信息读取的),将beanDefinition的ComponentScan里设置的包放入待过滤的包集合里,目前仅仅针对org和org.springframework包,

 

ServerPortInfoApplicationContextInitializer

 

SharedMetadataReaderFactoryContextInitializer

生产SharedMetadataReaderFactoryBean,并同时产生一个MetadataReader用于读取类的元数据,然后从容器获取了名为internalConfigurationAnnotationProcessor的BeanDefinition,把上面生成的metadataReaderFactory设置到它的属性中,后续BeanDefinitionReader在完成spring扫描时就会用它来完成一些Bean的元数据解析

 

AutoConfigurationReportLoggingInitializer

 

7.2 Load

加载我们启动类,将启动类注入容器

this.annotatedReader.register(source); 

以注解的方式,将启动类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 注解 默认为单例(singleton)

                   ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);

                   abd.setScope(scopeMetadata.getScopeName());

         //生成 beanName 获取启动类注解、子注解以及注解中所有的属性值,判断注解是否包含

org.springframework.stereotype.Component并且属性值存在value的,如果存在则取value值

作为beanName,否则根据类名生成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通知监听器,容器已准备就绪

触发ApplicationPreparedEvent事件

ConfigFileApplicationListener        增加PropertySourceOrderingPostProcessor

LoggingApplicationListener

BackgroundPreinitializer                 预初始化

DelegatingApplicationListener     扩展点 context.listener.classes

 

8 refreshContext刷新容器

执行到这里,springBoot相关的处理工作已经结束,接下的工作就交给了spring

prepareRefresh            在容器初始化前,做一些简单记录工作,同时初始一个容器所需的属性

 

8.1 obtainFreshBeanFactory

refreshBeanFactory()-> GenericApplicationContext. refreshBeanFactory,使用 CAS 改变 refreshed 标记,再给 BeanFactory 设置一个序列化 ID。

         getBeanFactory() 获取早已实例化的beanFactory

 

8.2 prepareBeanFactory

初始化一些组件,添加到BeanFactory 中

添加一个名为 ApplicationContextAwareProcessor 的 Bean 的后置处理器,是对spring中实现自Aware接口的bean等进行后置处理,ignoredDependencyInterfaces主要是缓存需要在bean进行属性注入时需要忽略的接口

添加一个 ApplicationListenerDetector 的 BeanPostProcessor,用于解析实现了ApplicationListener接口的bean

如果包含 loadTimeWeaver,则添加一个 LoadTimeWeaverAwareProcessor 的 BeanPostProcessor,与 AOP 有关,针对LoadTimeWeaverAware类型的bean设置LoadTimeWeaver,实现LoadTimeWeaverAware接口的类只有AspectJWeavingEnabler。

注册默认需要的 bean,environment、systemProperties、systemEnvironment

 

8.3 invokeBeanFactoryPostProcessors  

调用 BeanFactoryPostProcessors(Bean工厂后置处理器)

先调用实现了 BeanDefinitionRegistryPostProcessor 接口里的方法,保证所有 Bean 已注册到容器中,后调用实现了 BeanFactoryPostProcessor 接口里的方法,对 BeanFactory 进行修改,同时,BeanFactory 后置处理器是有调用顺序。

这里是 Spring 很重要的一个扩展点。通过配置配置的 Bean 都会被注册都容器中,同时程序员配置的 BeanFactory 后置处理器或是在 BeanFactory 后置处理器添加的后置处理器都会在这里执行。动态注册 BeanDefinition 是在这里完成的,同时程序员也可以实现相关接口在这里对已注册 BeanDefinition 进行修改。

postProcessBeanDefinitionRegistry->BeanFactoryPostProcessor

      代码解读:

 入参beanFactoryPostProcessors 已经注册的BeanFactoryPostProcessor       0{ConfigurationWarningsApplicationContextInitializer$ConfigurationWarningsPostProcessor@3691}

1{SharedMetadataReaderFactoryContextInitializer$CachingMetadataReaderFactoryPostProcessor@3692}

2{ConfigFileApplicationListener$PropertySourceOrderingPostProcessor@3693}

步骤:

1上面已注册的并且实现了BeanDefinitionRegistryPostProcessor的0和1,执行postProcessBeanDefinitionRegistry

2 获取实现了BeanDefinitionRegistryPostProcessor的并且实现了PriorityOrdered的,

执行postProcessBeanDefinitionRegistry

3 获取实现了BeanDefinitionRegistryPostProcessor的并且实现了Ordered的,

执行postProcessBeanDefinitionRegistry

4获取实现了BeanDefinitionRegistryPostProcessor的剩下的,执行postProcessBeanDefinitionRegistry

5 将1-4中涉及的实现了BeanDefinitionRegistryPostProcessor(也就是BeanFactoryPostProcessor)的后置处理器

执行invokeBeanFactoryPostProcessors->postProcessBeanFactory

      6获取实现了BeanFactoryPostProcessor,过滤掉上面已经执行过的,按照实现了PriorityOrdered接口、实现了

Ordered接口、剩余的优先级,执行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根据类上的注解判断配置类是FULL模式还是LITE模式

包含注解@Configuration,定义为full

包含注解@Component @ComponentScan @Import @ImportResource,定义为lite

Full lite作为是否加载过的标志

 

解析配置类

ConfigurationClassParser. Parse->processConfigurationClass->doProcessConfigurationClass

               // 把前面解析为 ConfigurationClass 类解析为 BeanDefinition 加入到 BeanDefinitionMap

      this.reader.loadBeanDefinitions(configClasses);

 

8.4 registerBeanPostProcessors  

实例化 Bean准备

spring 先添加 Bean 后置处理器 BeanPostProcessor,因为 BeanPostProcessor 会在实例化 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按照优先级分批实例化上面的14个beanPostProcessor,然后注册进来,并且实例化注册

BeanPostProcessorChecker、ApplicationListenerDetector

 

8.5 finishBeanFactoryInitialization

8.5.1 实例化Bean

instanceWrapper = createBeanInstance(beanName, mbd, args);之后,会返回一个实例化对象,但这个对象并不是一个完整的 Bean,Spring 在这之后调用 populateBean 方法完成属性注入。

8.5.2 populateBean

调用 Bean 后置处理器的 postProcessProperties 方法

InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;

pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);、

触发了

AutowiredAnnotationBeanPostProcessor. postProcessPropertyValues处理 @Autowired 注解

 

8.5.3 applyPropertyValues

上面只是将属性保存了起来,并未真正设置到 bean 中,这里设置到 bean 中

 

8.5.4 循环依赖

Spring中做三级缓存的三个容器:

一级缓存:singletonObjects,二级缓存:earlySingletonObjects,三级缓存:singletonFactories

 

入口: beanFactory.preInstantiateSingletons()

->DefaultListableBeanFactory. preInstantiateSingletons

->AbstractBeanFactory. doGetBean

->Object sharedInstance = getSingleton(beanName);

按顺序从1-3级缓存取bean,若从三级缓存取到,那么三级缓存->二级缓存        

    ->public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory)

此处是未能从三级缓存取到的,则要通过实例化获取

->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实例化完成但是未完成bean属性注入的,放三级缓存

         -> populateBean

               -> afterSingletonCreation

                            -> this.singletonsCurrentlyInCreation.remove(beanName)

                   -> addSingleton

                            -> this.singletonObjects.put(beanName, singletonObject);

                             Bean创建完成放入一级缓存