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创建完成放入一级缓存