Spring源码分析

写在前面的话,当前文章共有两部分,大览全局

Spring源码分析

SpringBoot的启动流程

Spring源码分析

AnnotationConfigApplicationContext

反推猜测应该完成什么?

  1. 生成bean对象 -> 创建beanFactory (bean工厂)
  2. BeanDefinition类 (加载bean信息, 通过注解得来的信息) -> 注解配置解析器AnnotationBeanDefinitionReader类

AnnotationBeanDefinitionReader中读取到不同的注解,有一系列的注解解析器去解析不同的注解

  1. 类路径扫描器 ClassPathBeanDefinitionScanner
  2. 系统属性扫描器 …

深入AnnotationConfigApplicationContext注解

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public AnnotationConfigApplicationContext(Class<?>... componentClasses) { // 配置类可以有多个
// 调用无参数构造函数, 初始化三个重要对象
// 1. DefaultListableBeanFactory工厂: 生成bean对象的beanFactory工厂
// 2. AnnotatedBeanDefinitionReader: 对加了特定注解(如@Service、@Repository)的类进行读取转换为BeanDefinition对象
// 还要注册各种处理器: registerAnnotationConfigProcessors(), 通过此方法添加各种内置处理器, 其中最重要的:
// 2.1 ★ConfigurationClassPostProcessor 是一个beanFactory后置处理器,用来完成bean的扫描与注入
// 2.2 AutowiredAnnotationBeanPostProcessor是一个bean的后置处理器, 依赖完成@Autowired自动注入
// 3. ClassPathBeanDefinitionScanner:对用户指定的包目录进行扫描查找bean对象的路径 扫描
this();
// 利用AnnotatedBeanDefinitionReader取将传进来的Configuration类做解析
// 将配置类Configuration注册到容器,但不实例化,其中最核心的方法为:doRegisterBean()
this.register(componentClasses);
// ***容器刷新*** @ComponentScan在这里完成解析
this.refresh();
}

this类中托管的各种注解解析器bean

this()方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public AnnotationConfigApplicationContext() {
super();//调用父类无参数构造方法,省略了
// startupStep类: 记录Application启动期间发生的特定阶段和操作的度量指标
StartupStep createAnnotatedBeanDefReader = this.getApplicationStartup().start("spring.context.annotated-bean-reader.create");
// 生成并注册BeanDefinition
// 配置类
//1.org.springframework.context.annotation.internalConfigurationAnnotationProcessor
// 自动配置
//2.org.springframework.context.annotation.internalAutowiredAnnotationProcessor
// 特定注解
//3.org.springframework.context.annotation.internalCommonAnnotationPostProcessor
// 事件监听
//4.org.springframework.context.event.internalEventListenerProcessor
// 工厂
//5.org.springframework.context.event.internalEventListenerFactory
this.reader = new AnnotatedBeanDefinitionReader(this);// 注解bean读取
createAnnotatedBeanDefReader.end();
// 注册默认的includeFilter
this.scanner = new ClassPathBeanDefinitionScanner(this);
}

至此发现还少了一个DefaultListableBeanFactory的工厂创建

构建工厂

super()

点进父类 (GenericApplicationContext) -> super()

1
2
3
4
5
6
public GenericApplicationContext() {
this.customClassLoader = false;
this.refreshed = new AtomicBoolean();
// 父类构造器中创建了一个bean工厂,默认列表bean工厂
this.beanFactory = new DefaultListableBeanFactory();
}

到这发现我们猜想的三个功能在this()中全部找到

注册各种处理器

this.reader = new AnnotatedBeanDefinitionReader(this)

注册处理器, 点进去

1
2
3
4
5
public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry) {
// 创建系统 属性及环境变量 getOrCreateEnvironment()
// 查看this(xx,yy)构造方法
this(registry, getOrCreateEnvironment(registry));
}

构造方法this(xx,yy),点进去

1
2
3
4
5
6
7
8
9
10
11
public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry, Environment environment) {
this.beanNameGenerator = AnnotationBeanNameGenerator.INSTANCE;
this.scopeMetadataResolver = new AnnotationScopeMetadataResolver();
Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
Assert.notNull(environment, "Environment must not be null");
this.registry = registry;
// 内部类用于解析 @Conditional注解
this.conditionEvaluator = new ConditionEvaluator(registry, environment, (ResourceLoader)null);
// 注册多种内置注解配置解析器
AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
}

深入AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
public static void registerAnnotationConfigProcessors(BeanDefinitionRegistry registry) {
registerAnnotationConfigProcessors(registry, (Object)null);
}

public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(BeanDefinitionRegistry registry, @Nullable Object source) {
// 创建Bean工厂 beanFactory
DefaultListableBeanFactory beanFactory = unwrapDefaultListableBeanFactory(registry);
if (beanFactory != null) {
// 逐步追加一些默认组件
// 第一个追加的组件 AnnotationAwareOrderComparator
if (!(beanFactory.getDependencyComparator() instanceof AnnotationAwareOrderComparator)) {
// 对@Order、@Priority、Ordered接口进行排序的比较类
beanFactory.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE);
}

if (!(beanFactory.getAutowireCandidateResolver() instanceof ContextAnnotationAutowireCandidateResolver)) {
// @Autowired @Qualifier @Lazy注解解析器
beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());
}
}
// BeanDefinitionHolder: 有名字和别名的
Set<BeanDefiniti onHolder> beanDefs = new LinkedHashSet(8);
RootBeanDefinition def;
// 判断容器是否有internalConfigurationAnnotationProcessor 这个bean
if (!registry.containsBeanDefinition("org.springframework.context.annotation.internalConfigurationAnnotationProcessor")) {
// 创建一个配置类处理器,托管成Bean ConfigurationClassPostProcessor
def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
// 补充一个属性值 source
def.setSource(source);
// 在registerPostProcessor()中将 RootBeanDefinition 包装成 BeanDefinitionHolder, 为什么?
// BeanDefinition添加了alias(别名)
// 另外, 注册此bean到容器是在 在registerPostProcessor完成的 (仅仅是加载到容器中)
beanDefs.add(registerPostProcessor(registry, def, "org.springframework.context.annotation.internalConfigurationAnnotationProcessor"));
}

if (!registry.containsBeanDefinition("org.springframework.context.annotation.internalAutowiredAnnotationProcessor")) {
// 没有则创建 AutowiredAnnotationBeanPostProcessor 并且托管
def = new RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, "org.springframework.context.annotation.internalAutowiredAnnotationProcessor"));
}
// 省略其他的处理器,当前仅留俩个样例
return beanDefs; // 返回BeanHolderProcess集合
}
梳理一下:

super() : 初始化bean工厂

new AnnotatedBeanDefinitionReader(this) : 创建各种各样的处理器

register注册配置类

注册@Configuration类

this.register(componentClasses)

1
2
3
4
5
6
7
8
9
10
public void register(Class<?>... componentClasses) {
// 断言
Assert.notEmpty(componentClasses, "At least one component class must be specified");
StartupStep registerComponentClass = this.getApplicationStartup().start("spring.context.component-classes.register").tag("classes", () -> {
return Arrays.toString(componentClasses);
});
// 注册配置类 (点进去)
this.reader.register(componentClasses);
registerComponentClass.end();
}

this.reader.register(componentClasses);

1
2
3
4
5
6
7
8
9
10
public void register(Class<?>... componentClasses) {
Class[] var2 = componentClasses;
int var3 = componentClasses.length;
// 循环遍历componentClass组件类
for(int var4 = 0; var4 < var3; ++var4) {
Class<?> componentClass = var2[var4];
// 注册bean
this.registerBean(componentClass);
}
}

真正注册bean 的方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
private <T> void doRegisterBean(Class<T> beanClass, @Nullable String name, @Nullable Class<? extends Annotation>[] qualifiers, @Nullable Supplier<T> supplier, @Nullable BeanDefinitionCustomizer[] customizers) {
// 解析包装传入的 Configuration类,变成AnnotatedGenericBeanDefinition对象
AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(beanClass);
// 判断是否要跳过,判断依据是此类上是否有@Conditional注解
if (!this.conditionEvaluator.shouldSkip(abd.getMetadata())) {
// 回调函数
abd.setInstanceSupplier(supplier);
// Scope值
ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);
// 默认设置scope是singleton
abd.setScope(scopeMetadata.getScopeName());
// 如果有定义bean的名字则用定义的,否则则获取并生成
String beanName = name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry);
// 处理类上面的通用注解: 如@Lazy @Primary @DependsOn,解析出左边的注解,保存到BeanDefinition中
AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);
int var10;
int var11;
if (qualifiers != null) {
Class[] var9 = qualifiers;
var10 = qualifiers.length;

for(var11 = 0; var11 < var10; ++var11) {
Class<? extends Annotation> qualifier = var9[var11];
if (Primary.class == qualifier) {
abd.setPrimary(true);
} else if (Lazy.class == qualifier) {
abd.setLazyInit(true);
} else {
abd.addQualifier(new AutowireCandidateQualifier(qualifier));
}
}
}
// 用户自定义注解
if (customizers != null) {
// 类必须实现BeanDefinitionCustomizer接口
BeanDefinitionCustomizer[] var13 = customizers;
var10 = customizers.length;

for(var11 = 0; var11 < var10; ++var11) {
BeanDefinitionCustomizer customizer = var13[var11];
customizer.customize(abd);
}
}
// 到此还没有实例化,仅仅是构建了一个BeanDefinitionHolder
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);
// 应用scopeProxyMode 代理模式
definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
// 把BeanDefinitionHolder注册到registry容器中
BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
// registerBeanDefinition注册bean
}
}
梳理一下:

三步:

  1. this()注册了默认的Bean
  2. register()注册配置类的Bean (registerBeanDefinition()方法)
  3. 那么还剩一个refresh则是用于 注册自定义的Bean

refresh()所有的 bean 的创建以及初始化

Spring的refresh()方法会触发所有bean的创建初始化过程。当调用refresh()方法时,Spring容器会执行一系列的步骤,包括创建BeanFactory、加载Bean定义、实例化Bean、依赖注入、初始化Bean等。

refresh()方法中,Spring会遍历所有注册的Bean定义,根据定义创建相应的Bean实例,并对这些实例进行初始化。这个过程包括调用Bean的构造函数创建实例,设置Bean的属性值,执行Bean的初始化方法等。这样,所有的Bean都会经过这个过程,完成它们的创建和初始化。

需要注意的是,refresh()方法并不会销毁已经存在的Bean实例。它主要用于重启Spring容器,重新加载和初始化Bean。如果需要销毁已经存在的Bean实例,可以使用destroy()方法或者通过配置合适的作用域(如prototype)来控制Bean的生命周期。

非常重要的方法 invokeBeanFactoryPostProcessors bean工厂的后置处理器

Refresh()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
public void refresh() throws BeansException, IllegalStateException {
synchronized(this.startupShutdownMonitor) {// 设置同步标识
StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");
// Prepare this context for refreshing.
// 1. 调用容器准备刷新的方法, 获取容器的时间,包括设置上下文状态,获取属性,验证必要的属性等
// ▶可以实现initPropertySources()方法, 添加属性或设置需要验证的属性
this.prepareRefresh();
// Tell the subclass to refresh the internal bean factory
// 2. ★★★★★获取新的beanFactory,刷新BeanFactory和获取getBeanFactory --> 获取IOC容器
// 如果在这里断点,只会发现它仅仅完成了beanFactory设置序列化id
ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();
// Prepare the bean factory for use in this context, 为BeanFactory配置容器亏秤,如类加载器,事件处理器
// 3. 填充BeanFactory功能, 配置容器特性
// 例如设置ClassLoader,设置SpEL表达式解析器,添加忽略注入的接口,添加三个和环境相关的bean (SpEL: 例如@Value("#{name}"))
// 添加两个bean后置处理器BeanPostProcessor(ApplicationContextAwareProcessor和ApplicationListenerDetector)等
this.prepareBeanFactory(beanFactory);

try {
// Allows post-processing of the bean factory in context subclasses
// 4. 在这里是空方法(模版语法),子类可以重写这个方法,可以在BeanFactory创建并与准备完成后做进一步的设置
// 即子类处理自定义的BeanFactoryPostProcess
this.postProcessBeanFactory(beanFactory);// 为容器的子类指定特殊的post事件处理器
StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");
/*
以下两点是关于后置处理器的激活
Spring中会发现有很多后置处理器,但最终可以分为两种
(1)BeanFactoryPostProcessor,用于干预BeanFactory的创建过程
(2)BeanPostProcessor,用于干预Bean的创建过程
后置处理器的作用非常重要,Bean的创建以及AOP的实现全部依赖后置处理器
*/
// Invoke factory processor registered as beans in the context
// 5. ★★★★★ 激活各种BeanFactory处理器,调用所有注册的BeanFactoryPostProcessor的Bean
// BeanFactoryPostProcessor可以在工厂初始化后,让用户做一些定制型的工作.(实现此BeanFactoryPostProcessor接口)
// 执行所有的BeanFactoryPostProcessor,包括自定义的,以及Spring内置的
// 默认情况下,容器中只有一个BeanFactoryPostProcessor,即Spring内置的ConfigurationClassPostProcessor(★这个类很重要)
// 会先执行实现了BeanDefinitionRegistryPostProcessor接口的类,然后执行BeanFactoryPostProcessor的类
// ★★★★ ConfigurationClassPostProcessor类的postProcessorBeanFactory()方法进行了@Configuration类的解析,@ComponentScan的扫描,@Import注解的处理
// 进过了这一步以后,会将所有交由Spring管理的bean对应的BeanDefinition放入beanFactory的beanDefinitionMap中
// 同时ConfigurationClassPostProcessor类的postProcessorBeanFactory()方法执行完后:
// 向容器中添加了一个后置处理器-- ImportAwareBeanPostProcessor
this.invokeBeanFactoryPostProcessors(beanFactory);//★★★★★★ 及其重要,在这里完成了 @ComponentScan的扫描,@Import注解的处理
// Register bean processor that intercept creation.
// 6. ★★★注册BeanPostProcessor后置处理器
// AutowiredAnnotationBeanPostProcessor(处理被@Autowired注解修饰的bean,并注入)
// RequiredAnnotationBeanPostProcessor(处理被@Required注解修饰的方法)
// CommonAnnotationBeanPostProcessor(处理@PreDestroy @PostConstruct @Resource等多个注解的作用)等
// AutoProxyCreator(处理AOP代理 @Aspect)
this.registerBeanPostProcessors(beanFactory);
beanPostProcess.end();
// 7. 初始化信息源(做国际化功能: 消息绑定,消息解析)
this.initMessageSource();
// 8. 初始化事件派发器,在注册监听器时会用到
this.initApplicationEventMulticaster();
// 9. 这也是一个挂载点,一个空方法,由子类实现(不同的Spring容器做不同的实现),在容器监听的时候可以自定义逻辑
this.onRefresh();
// 10. 注册监听器,派发之前步骤产生的一些事件(尽可能没有)
this.registerListeners();
// 11. ***** 初始化剩下的单例Bean(非延时加载的) 真正的初始化bean的方法
this.finishBeanFactoryInitialization(beanFactory);
// 12. 初始化容器的生命周期事件处理器,并发布容器的生命周期事件
this.finishRefresh();
} catch (BeansException var10) {
if (this.logger.isWarnEnabled()) {
this.logger.warn("Exception encountered during context initialization - cancelling refresh attempt: " + var10);
}

this.destroyBeans();
this.cancelRefresh(var10);
throw var10;
} finally {
this.resetCommonCaches();
contextRefresh.end();
}

}
}

@ComponentScan属性的读取

逐步读取

目标: 读取basePackages设置的类

寻找的目录指引如下:(以下每一步操作均为追踪描述方法后的指引介绍)

  1. 入口 AnnotationConfigApplicationContext
  2. 当前类下的构造器实现重载解析类的方法 找到refresh(),
  3. ★invokeBeanFactoryPostProcessors方法(重要),
  4. 然后可以找到一个后置处理器的委托代理类 (PostProcessorRegistrationDelegate) ,其中有方法为invokeBeanFactoryPostProcessors
  5. 在当前方法中找到 if-else中的invokeBeanFactoryPostProcessors方法(中间处理bean工厂类上加了注解的,比如@Primary,@Order排序), 不论走if还是else 都会激活bean工厂的后置处理器

invokeBeanFactoryPostProcessors

  1. 找到postProcessor.postProcessBeanFactory(beanFactory)这一行, 当前行为后置处理器处理bean工厂, 点进postProcessBeanFactory方法发现什么都没有, 他是一个@FunctionalInterface接口(函数接口), 找实现类(如下图),
  1. 找到 postProcessBeanFactory 方法(bean工厂的后置处理器)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
int factoryId = System.identityHashCode(beanFactory);
if (this.factoriesPostProcessed.contains(factoryId)) {
throw new IllegalStateException("postProcessBeanFactory already called on this post-processor against " + beanFactory);
} else {
this.factoriesPostProcessed.add(factoryId);
// BeanDefinitionRegistryPostProcessor hook apparently not supported...
// Simply call processConfigurationClasses lazily at this point then
// 判断已注册的PostProcessor是否包含了factoryId
if (!this.registriesPostProcessed.contains(factoryId)) {
// ★正式处理配置Bean定义 @Configuration -> 里面带了一个@ComponentScan
this.processConfigBeanDefinitions((BeanDefinitionRegistry)beanFactory);
}
// 代理
this.enhanceConfigurationClasses(beanFactory);
// Import感知 @Import({A.class})
beanFactory.addBeanPostProcessor(new ImportAwareBeanPostProcessor(beanFactory));
}
}
  1. 追踪processConfigBeanDefinitions
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
List<BeanDefinitionHolder> configCandidates = new ArrayList();
String[] candidateNames = registry.getBeanDefinitionNames();
String[] var4 = candidateNames;
int var5 = candidateNames.length;
// 迭代所有候选的bean名字
for(int var6 = 0; var6 < var5; ++var6) {
String beanName = var4[var6];
BeanDefinition beanDef = registry.getBeanDefinition(beanName);
// 判断上面是否包含ConfigurationClass属性
if (beanDef.getAttribute(ConfigurationClassUtils.CONFIGURATION_CLASS_ATTRIBUTE) != null) {
// 略 (如果有则加入候选)
}

if (!configCandidates.isEmpty()) {
// 配置类候选排序(@Order,@Priority排序标志)
configCandidates.sort((bd1, bd2) -> {
int i1 = ConfigurationClassUtils.getOrder(bd1.getBeanDefinition());
int i2 = ConfigurationClassUtils.getOrder(bd2.getBeanDefinition());
return Integer.compare(i1, i2);
});
SingletonBeanRegistry sbr = null;
// 检查是否为单例bean
if (registry instanceof SingletonBeanRegistry) {
sbr = (SingletonBeanRegistry)registry;
if (!this.localBeanNameGeneratorSet) {
BeanNameGenerator generator = (BeanNameGenerator)sbr.getSingleton("org.springframework.context.annotation.internalConfigurationBeanNameGenerator");
if (generator != null) {
this.componentScanBeanNameGenerator = generator;
this.importBeanNameGenerator = generator;
}
}
}
// 环境,如果没有则标准环境
if (this.environment == null) {
this.environment = new StandardEnvironment();
}
// Parse each @Configuration class
// ★★★★解析每一个@Configuration类,包括@ComponentScan
ConfigurationClassParser parser = new ConfigurationClassParser(this.metadataReaderFactory, this.problemReporter, this.environment, this.resourceLoader, this.componentScanBeanNameGenerator, registry);
// 上述配置类解析器包括:注解元信息的读取工厂、问题报告器、标准系统环境变量、资源加载器、组件扫描bean名字构建器
Set<BeanDefinitionHolder> candidates = new LinkedHashSet(configCandidates);
Set<ConfigurationClass> alreadyParsed = new HashSet(configCandidates.size());

do {// 一个一个的读取候选的配置(可以有多个配置类,一次读取一个)
StartupStep processConfig = this.applicationStartup.start("spring.context.config-classes.parse");
// ★★★★★★ 真正的解析器在此
parser.parse(candidates); // candidate 候选集合(多个配置类)

parser.validate();
Set<ConfigurationClass> configClasses = new LinkedHashSet(parser.getConfigurationClasses());
// 下面代码略
}
}
  1. 追踪parse (8中源码注释标★★★★★★)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public void parse(Set<BeanDefinitionHolder> configCandidates) {
Iterator var2 = configCandidates.iterator();
// 循环迭代每一个Configuration类,parse()解析
while(var2.hasNext()) {
BeanDefinitionHolder holder = (BeanDefinitionHolder)var2.next();
BeanDefinition bd = holder.getBeanDefinition();
// 开始判断注解属于什么类
try {
if (bd instanceof AnnotatedBeanDefinition) {
this.parse(((AnnotatedBeanDefinition)bd).getMetadata(), holder.getBeanName());
} else if (bd instanceof AbstractBeanDefinition && ((AbstractBeanDefinition)bd).hasBeanClass()) {
this.parse(((AbstractBeanDefinition)bd).getBeanClass(), holder.getBeanName());
} else {
this.parse(bd.getBeanClassName(), holder.getBeanName());
}
}
// catch异常处理处(略)
}
this.deferredImportSelectorHandler.process();
}

在此处总结发现, 源码中凡是嵌套if-eles的, 最后都会调用 同一个方法, 方法的重载

  1. 继续追踪重载的parse
1
2
3
4
5
6
7
protected final void parse(@Nullable String className, String beanName) throws IOException {
Assert.notNull(className, "No bean class name for configuration class bean definition");
// 元数据读取
MetadataReader reader = this.metadataReaderFactory.getMetadataReader(className);
// ★ 处理配置类
this.processConfigurationClass(new ConfigurationClass(reader, beanName), DEFAULT_EXCLUSION_FILTER);
}
  1. 追踪processConfigurationClass,★★★★★然后追踪do-while里面的递归处理配置类

在此处先是处理条件注解@Conditional, 然后判断配置类, 没导入则合并 marginImport

do-while中递归读取配置类方法doProcessConfigurationClass.

在@Configuration注解中它包括了@Component注解.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
@Nullable
protected final SourceClass doProcessConfigurationClass(ConfigurationClass configClass, SourceClass sourceClass, Predicate<String> filter) throws IOException {
// 第一步判断配置类上是否有@Component注解
if (configClass.getMetadata().isAnnotated(Component.class.getName())) {
this.processMemberClasses(configClass, sourceClass, filter);
}
// 属性资源读取 (eg: @PropertySource("classpath:db.properties"))
Iterator var4 = AnnotationConfigUtils.attributesForRepeatable(sourceClass.getMetadata(), PropertySources.class, PropertySource.class).iterator();

AnnotationAttributes importResource;
while(var4.hasNext()) {
importResource = (AnnotationAttributes)var4.next();
// 有则处理
if (this.environment instanceof ConfigurableEnvironment) {
this.processPropertySource(importResource);
} else {
this.logger.info("Ignoring @PropertySource annotation on [" + sourceClass.getMetadata().getClassName() + "]. Reason: Environment must implement ConfigurableEnvironment");
}
}
// ★★★★★目标到达★★★★★
Set<AnnotationAttributes> componentScans = AnnotationConfigUtils.attributesForRepeatable(sourceClass.getMetadata(), ComponentScans.class, ComponentScan.class);
// 如果包扫描注解不是空 并且 不跳过
if (!componentScans.isEmpty() && !this.conditionEvaluator.shouldSkip(sourceClass.getMetadata(), ConfigurationPhase.REGISTER_BEAN)) {
// 迭代器遍历包扫描的注解
Iterator var14 = componentScans.iterator();

while(var14.hasNext()) {

AnnotationAttributes componentScan = (AnnotationAttributes)var14.next();
// The config class is annotated with @ComponentScan -> perform the scan immediatel
// ★★★★★ 这个parse真正处理@ComponentScan中的basePackages
Set<BeanDefinitionHolder> scannedBeanDefinitions = this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());
Iterator var8 = scannedBeanDefinitions.iterator();
// Check the set of scanned definitions for any further config classes and parse recursively if needed
while(var8.hasNext()) {
BeanDefinitionHolder holder = (BeanDefinitionHolder)var8.next();
BeanDefinition bdCand = holder.getBeanDefinition().getOriginatingBeanDefinition();
if (bdCand == null) {
bdCand = holder.getBeanDefinition();
}

if (ConfigurationClassUtils.checkConfigurationClassCandidate(bdCand, this.metadataReaderFactory)) {
this.parse(bdCand.getBeanClassName(), holder.getBeanName());
}
}
}
}
// @Import
this.processImports(configClass, sourceClass, this.getImports(sourceClass), filter, true);
importResource = AnnotationConfigUtils.attributesFor(sourceClass.getMetadata(), ImportResource.class);
// 略
return null;
}

对于上述源码的parse:

  1. 首先建立了一个ClassPathBeanDefinitionScanner扫描器, 扫描@ComponentScan, 以及是否要过滤(includeFilters)

  2. 包扫描器获取名字, 获取作用域(设置), 资源模式, 扫描过滤条件(包含过滤器,扫描过滤器), 判断是否为懒加载(lazyInit)

  3. ★★★★★ 期盼的 (扫描basePackages)

    1
    2
    3
    4
    5
    // 情况一 basePackages
    Set<String> basePackages = new LinkedHashSet();
    String[] basePackagesArray = componentScan.getStringArray("basePackages");
    // 情况二 basePackageClasses
    Class[] var20 = componentScan.getClassArray("basePackageClasses");
  4. 判断是否为空, 假如为空, 则获取当前注解类的包路径

  5. 最后看看是否有筛选, 过滤

到此,包名准备完毕, 然后 递归扫描

1
return scanner.doScan(StringUtils.toStringArray(basePackages));

doScan递归扫描

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
/*
1. 资源扫描
扫描包路径下.class文件, 将资源转换为Resource
2. 资源加载
通过ASM框架获取class元数据,封装BeanDefinition
3. 资源解析
获取bean上注解的属性值, 如@Scope
4. 生成Bean
生成beanName, 设置Bean默认值(懒加载,初始化方法等) 代理模式
5. 注册Bean
把BeanDefinition放入IOC容器DefaultListableBeanFactory
*/
protected Set<BeanDefinitionHolder> doScan(String... basePackages) {
Assert.notEmpty(basePackages, "At least one base package must be specified");
//创建一个集合,存放扫描到的Bean定义封装类
// 无序,不可重复, BeanDefinitionHolder包了一个BeanDefinition: bean的定义类:关于一个bean所有的相关信息
// (scope,lazy,initmethod,destroymethod...)
Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<>();
//遍历扫描所有给定的包路径
for (String basePackage : basePackages) {
//** 调用父类ClassPathScanningCandidateComponentProvider的方法
// 扫描指定类路径, 获取符合条件的Bean定义, 并存入集合beanDefinitions中
Set<BeanDefinition> candidates = findCandidateComponents(basePackage);
//遍历BeanDefinition (扫描到的bean)
for (BeanDefinition candidate : candidates) {
//** 获取@Scope的值,即获取scope的作用域, scope取值: singleton,prototype
ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);
// 为bean 设置作用域
candidate.setScope(scopeMetadata.getScopeName());
//** 为bean生成名字
String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);
// 设置Bean的自动依赖注入装配属性等 ****这里每一个bean 先设置默认值(lazy,autowiredMode,dependency,init,destroy)
if (candidate instanceof AbstractBeanDefinition) {
//* -> applyDefaults 给默认值设置一个bean的属性
postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName);
}
// 如果扫描到的bean是Spring的注解bean,则处理其通用的Spring注解
// 再设置这个bean上的用户配置值
if (candidate instanceof AnnotatedBeanDefinition) {
//** 解析通用注解(@Lazy、@Primary、@DependsOn、@Role、@Description注解),为这些注解设置值
AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);
}
// 冲突检查
if (checkCandidate(beanName, candidate)) {
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
definitionHolder =
AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
beanDefinitions.add(definitionHolder);

//** 在容器中注册扫描到的bean
registerBeanDefinition(definitionHolder, this.registry);
}
}
}
return beanDefinitions;
}

简化注册扫描

以往

1
2
ApplicationContext context =
new AnnotationConfigApplicationContext(SpringConfig.class);

通过读取配置类, 然后读取配置类上面的@ComponentScan注解, 然后在扫描

现在

1
2
ApplicationContext context =
new AnnotationConfigApplicationContext(basePackages = "com.spring");

通过使用AnnotationConfigApplicationContext的重载方法, 直接扫描指定的basePackages路径, 省略了读取配置类在读取注解的流程

使用这个方案, 也就是直接走到了 scanner.doScan(StringUtils.toStringArray(basePackages));方法而不需要绕来绕去的解析

缺点: 路径固定

上部分小总结

refresh

实例化(循环依赖)

流程了解

既然都得到了扫描到的对象 Set<BeanDefinition>

接下来需要做的就是实例化对象了

其中实例化包括

  1. @Value 设置属性
  2. @Autowired 注入依赖

然后 存入map

通过getBean()获取IOC容器中的bean

从容器中取的流程:

  • 懒加载模式: content.getBean() -> getBean -> doGetBean()
  • 非懒加载模式: finishBeanFactoryInitialization() -> beanFactory.preInstantiateSingletons() 生成一个单例bean -> getBean() -> doGetBean()

所以两类都是殊途同归 doGetBean()

如何解决循环依赖

循环依赖, 依赖成为一个环, 互相依赖

构造方法循环依赖
  1. 在构造器循环依赖的每一个构造器上面加注解@Lazy

  2. 代码重构

  3. 改为字段依赖注入

使用注意点是:

@Lazy注解:

  • 初始化注入代理对象时, 真实调用时使用Spring AOP动态代理去关联真实对象, 然后通过反射完成调用
  • 加在构造器上, 作用域为构造器所有参数, 加在某个参数上, 作用域为该参数
  • 作用在接口上, 使用JDK动态代理, 这样在类上, 使用CGLib动态代理
Setter循环依赖

字段注入循环依赖,Spring官方通过三层缓存解决, 解决方案:

setter注入下 实例化 (无参构造方法) 和依赖属性注入**(set或属性)**是分开的, 这是其可以解决循环依赖最根本的原因

getBean中创建Bean的流程
doGetBean()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
protected <T> T doGetBean(
String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
throws BeansException {
// 根据指定的名称获取被管理的Bean的名字, 剥离指定名称中对容器的相关依赖
// 如果指定的是别名,那么将别名转换为规范的Bean名称
// <1>获取beanName: 传入参数name可能是别名,也有可能是FactoryBean, 所以需要一系列的解析
// 为FactoryBean时,name为 "&工厂名" ,还要别名的情况
String beanName = transformedBeanName(name);
Object beanInstance;

// Eagerly check singleton cache for manually registered singletons.
// 从缓存中获取已被创建过的单例Bean
// ***<2>从缓存中获取单例bean,避免循环依赖
Object sharedInstance = getSingleton(beanName);// 单例模型 (getSingleton方法看下面源码部分)
// 如果缓存中有此单例Bean
if (sharedInstance != null && args == null) {
if (logger.isTraceEnabled()) {
if (isSingletonCurrentlyInCreation(beanName)) {
logger.trace("Returning eagerly cached instance of singleton bean '" + beanName +
"' that is not fully initialized yet - a consequence of a circular reference");
}
else {
logger.trace("Returning cached instance of singleton bean '" + beanName + "'");
}
}
beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}

else{
// 省略
}
finally {
beanCreation.end();
}
}

return adaptBeanInstance(name, beanInstance, requiredType);
}
getSingleton()

只有单例才会有这个,原型模式不会调用此方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
// Spring对单例的bean只会创建一次,后续获取则都是在缓存中获取
// 该过程体现在 #getSingleton(String beanName)中
/*
三级缓存机制的理解: 目标避免循环依赖
一级: 从singletonObjects获取实例
否则:从earlySingletonObjects获取
否则: 从singletonFactories获取beanName对应的ObjectFactory,在调用getObject()来创建bean,并放到earlySingletonObjects中
并从singletonFactories中删除此ObjectFactory
*/
@Nullable
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
// Quick check for existing instance without full singleton lock
// 从单例缓存(一级缓存)中获取单例bean: 用来存已经完成初始化的单例bean
Object singletonObject = this.singletonObjects.get(beanName);
// 如果缓存中没有 并且 该bean真正创建(在singletonsCurrentlyInCreation集中存在此bean的名字)
// ★★★ isSingletonCurrentlyInCreation(beanName)
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
// 从二级缓存earlySingletonObjects中取 已经创建但是没有属性注入
singletonObject = this.earlySingletonObjects.get(beanName);
// earlySingletonObjects中没有,且运行提前创建
if (singletonObject == null && allowEarlyReference) {
// 双重检查锁

// 防止重复创建,使用正式创建bean前锁定(单例模型的双重检查锁:当前判断了两次singletonObject,在锁之前和锁之后)
synchronized (this.singletonObjects) {
// Consistent creation of early reference within full singleton lock
singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
// earlySingletonObjects中没有,且运行提前创建
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null) {
// 从三级缓存 singletonFactories 中获取对应的ObjectFactory
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null) {
// 从单例工厂中获取bean
singletonObject = singletonFactory.getObject();
// 存入(early, 注意此时还没有添加属性(populateBean用来注入属性的),添加到二级缓存)
this.earlySingletonObjects.put(beanName, singletonObject);
// 从三级缓存中删除
this.singletonFactories.remove(beanName);
}
}
}
}
}
}
return singletonObject;
}

三级缓存的理解:目标避免循环依赖
一级: 从singletonObjects获取实例
二级——>否则:从earlySingletonObjects获取
三级————>否则: 从singletonFactories获取beanName对应的ObjectFactory,在调用getObject()来创建bean,并放到earlySingletonObjects中
——————>并从singletonFactories中删除此ObjectFactory


一级缓存(singletonObjects): 是一个完整的Bean -

二级缓存(earlySingletonObjects): bean的实例,但是没有属性( 属性还没有注入,所以说构造方式没办法解决循环依赖,set注入可以 ) , 早期的bean

三级缓存(singletonFactories ): 存放bean的原始工厂,其内容与二级缓存中的无异

Spring解决循环依赖(在此仅考虑set/属性注入,单例情况)是依靠Bean的中间态(一级:完整bean 二级:没有属性的bean 三级;ObjectFactory)这个概念, 而中间态是指bean的初始化状态

实例化的过程又是通过构造器创建的,如果A还没创建出来就不能提前曝光(对象工厂,三级缓存ObjectFactory), 所以构造器的循环依赖无法解决


双重检查锁: 单例, 在一级缓存和二级缓存后加锁,加锁后再走一遍判断一级二级缓存中是存在singletonObject对象

SpringBoot的启动流程

简要概述

​ 我们的springboot项目是通过SpringApplication.run(class)方法启动的。传进去的那个类一般是我们的启动类。run方法的底层会先包装一个SpringApplication对象。在构造函数里面会通过依赖的包确定我们运行的web环境(servlet还是reactive),保存我们传进去的启动类,从spring.factories文件中加载初始化器监听器

​ 对象创建好后,调用他的run方法,也就是springboot启动的核心。里面会创建StopWatch对项目启动进行计时。会根据web类型,创建不同的上下文context。会打印项目启动的banner。有两个比较核心的操作,是容器初始化容器刷新的操作。

容器初始化会调用对象保存的所有初始化器,这些初始化器可能会对cntext进行一些配置,或者注册一些bean进去。同时也会把之前传进去的启动类注册成bean,这样后续能够根据启动类的注解@SpringBootApplication扫描项目路径下的包和自动装配的类。

容器刷新就是调用spring上下文原生的refresh方法,进行容器的刷新逻辑。

​ 在这期间,不同的阶段,springboot都会通知给监听器,如果我们关心这些阶段想做对应动作,可以实现SpringApplicationRunListener或者ApplicationListener 类,,并且要在spring.factories文件中配置。

​ 最后容器启动成功,会通知给监听器,如果我们想获得更多信息,比如run的args,也可以实现ApplicationRunnerCommandLineRunner方法。一般做一些预热或者初始化操作可以用这个方法。

源码级追踪

对于一个SpringBoot项目,在前置准备全部完成后,我们的入口会是这样的

1
2
3
4
5
6
@SpringBootApplication
public class CalyeeApplication {
public static void main(String[] args) {
SpringApplication.run(CalyeeApplication.class, args);
}
}

@SpringBootApplication

对于SpringBootApplication注解,其实他是一个复合注解

1
2
3
4
5
6
7
8
9
10
11
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(
excludeFilters = {@Filter(
type = FilterType.CUSTOM,
classes = {TypeExcludeFilter.class}
), @Filter(
type = FilterType.CUSTOM,
classes = {AutoConfigurationExcludeFilter.class}
)}
)
@SpringBootConfiguration

对于这个注解,其实他就是一个Spring的@Configuration注解,他标明这个类需要作为一个配置类给Spring IOC托管

1
2
3
4
5
6
7
8
9
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Configuration // <-
@Indexed
public @interface SpringBootConfiguration {
@AliasFor(annotation = Configuration.class)
boolean proxyBeanMethods() default true;
}
@ComponentScan

这个其实也没什么,其实就是组件的扫描,然后里面还可以编写一些过滤逻辑/排除逻辑(excludeFilters、@Filter)

@EnableAutoConfiguration

这个注解才是实现自动装配的关键,点进去之后发现,它是一个由@AutoConfigurationPackage和@lmport
注解组成的复合注解。

1
2
3
4
5
6
7
8
9
10
11
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import({AutoConfigurationImportSelector.class})
public @interface EnableAutoConfiguration {
String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";
Class<?>[] exclude() default {};
String[] excludeName() default {};
}

@lmport导入了一个类AutoConfigurationImportSelector.class,在有之前阅读过源码的经验,这个其实就是自动装配导入选择器,在此仅列出类继承部分

1
public class AutoConfigurationImportSelector implements DeferredImportSelector, BeanClassLoaderAware, ResourceLoaderAware, BeanFactoryAware, EnvironmentAware, Ordered {

具体自动装配的路径跟踪,笔者可以沿着 AutoConfigurationImportSelector(类):org.springframework.boot.autoconfigure.AutoConfigurationlmportSelector#getCandidateConfiguration

SpringFactoriesLoader.loadFactoryNames这个方法就是加载spring.factories的所有某个类型的数
据。根据第一个参数,就是查出所有自动装配的类(其实这个可以看作SPI在SpringBoot中的运用)

这样就会在beanDefinetion阶段把这些自动装配的类注册进去了。

对象创建

沿着run方法追踪进去,他构建了一个SpringApplication对象,然后再调用run方法启动SpringBoot项目,其中我们可以发现有

1
2
3
public static ConfigurableApplicationContext run(Class<?>[] primarySources, String[] args) {
return new SpringApplication(primarySources).run(args);
}

#SpringApplication

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
this.resourceLoader = resourceLoader;
Assert.notNull(primarySources, "PrimarySources must not be null");
//设置源
//通常Springboot的启动类就是源
this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
//推断并设置WEB应用程序类型
//根据classpath下的类来推断
this.webApplicationType = WebApplicationType.deduceFromClasspath();
//加载并设置Bootstrapper
this.bootstrapRegistryInitializers = new ArrayList<>(
getSpringFactoriesInstances(BootstrapRegistryInitializer.class));
//加载并设置初始化器
setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
//加载并设置应用事件监听器
setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
//推断并设置应用程序主类的class对象
this.mainApplicationClass = deduceMainApplicationClass();
}

其中SpringApplication中的构造函数就是做了如下的事件:

  1. 设置源,其中在SpringBoot中的源一般都是SpringBoot的启动类
  2. 设置Web应用程序类型。通过判断classpath下是否存在某些类,来推断当前WEB应用程序的类型
  3. 加载并设置Bootstrapper,ApplicationContextlnitializer和ApplicationListener。借助
    SpringFactoriesLoader基于SPI机制完成Bootstrapper,ApplicationContextlnitializer和
    ApplicationListener的加载,然后设置到SpringApplication中;
  4. 设置应用程序主类的Class对象。
设置源

在SpringBoot中,一般源都为SpringBoot的启动类本身

设置Web应用程序类型

WebApplicationType#deduceFromClasspath

1
2
3
4
5
6
7
8
9
10
11
12
static WebApplicationType deduceFromClasspath() {
if (ClassUtils.isPresent(WEBFLUX_INDICATOR_CLASS, null) && !ClassUtils.isPresent(WEBMVC_INDICATOR_CLASS, null)
&& !ClassUtils.isPresent(JERSEY_INDICATOR_CLASS, null)) {
return WebApplicationType.REACTIVE;
}
for (String className : SERVLET_INDICATOR_CLASSES) {
if (!ClassUtils.isPresent(className, null)) {
return WebApplicationType.NONE;
}
}
return WebApplicationType.SERVLET;
}

其实就是判断是不是Servlet(目前MVC常用的)

加载并设置Bootstrapper

SpringApplication#getSpringFactoriesInstances

1
2
3
4
5
6
7
8
9
private <T> Collection<T> getSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes, Object... args) {
ClassLoader classLoader = getClassLoader();
// Use names and ensure unique to protect against duplicates
// 通过SpringFactoriesLoader加载工厂名的类
Set<String> names = new LinkedHashSet<>(SpringFactoriesLoader.loadFactoryNames(type, classLoader));
List<T> instances = createSpringFactoriesInstances(type, parameterTypes, classLoader, args, names);
AnnotationAwareOrderComparator.sort(instances);
return instances;
}

其实就是跟之前的自动装配很像,他也是拿全限定名 例如

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# Application Context Initializers
org.springframework.context.ApplicationContextInitializer=\
org.springframework.boot.context.ConfigurationWarningsApplicationContextInitializer,\
org.springframework.boot.context.ContextIdApplicationContextInitializer,\
org.springframework.boot.context.config.DelegatingApplicationContextInitializer,\
org.springframework.boot.rsocket.context.RSocketPortInfoApplicationContextInitializer,\
org.springframework.boot.web.context.ServerPortInfoApplicationContextInitializer

# Application Listeners
org.springframework.context.ApplicationListener=\
org.springframework.boot.ClearCachesApplicationListener,\
org.springframework.boot.builder.ParentContextCloserApplicationListener,\
org.springframework.boot.context.FileEncodingApplicationListener,\
org.springframework.boot.context.config.AnsiOutputApplicationListener,\
org.springframework.boot.context.config.DelegatingApplicationListener,\
org.springframework.boot.context.logging.LoggingApplicationListener,\
org.springframework.boot.env.EnvironmentPostProcessorApplicationListener

那么在此可以发现,与自动装配不同的是,这次拿的不是那些自动配置类 如:MyBatisPlusAutoConfiguration

查到这些类的全限定名后,就调用它们的无参构造器进行实例化,并保存起来,方便后续在run代码里调用。

设置应用程序主类的Class对象
1
2
3
4
5
6
7
8
9
10
11
12
13
14
private Class<?> deduceMainApplicationClass() {
try {
StackTraceElement[] stackTrace = new RuntimeException().getStackTrace();
for (StackTraceElement stackTraceElement : stackTrace) {
if ("main".equals(stackTraceElement.getMethodName())) {
return Class.forName(stackTraceElement.getClassName());
}
}
}
catch (ClassNotFoundException ex) {
// Swallow and continue
}
return null;
}

通过当前堆栈找到主类

执行Run方法启动项目

SpringApplication#run(String… args)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
/**
* Run the Spring application, creating and refreshing a new
* {@link ApplicationContext}.
* @param args the application arguments (usually passed from a Java main method)
* @return a running {@link ApplicationContext}
*/
public ConfigurableApplicationContext run(String... args) {
long startTime = System.nanoTime();// 记录启动时间(其实就是用于记录启动的时间)
DefaultBootstrapContext bootstrapContext = createBootstrapContext();
ConfigurableApplicationContext context = null;
configureHeadlessProperty();
//[1] 从spring.factories加载配置的SpringApplicationRunListener,springboot黑认引入EventPublishingRunListener
//EventPublishingRunListener对象主要用来发射SpringBoot启动过程中内置的一些生命周期事件,通知给ApplicationListener
//其实就是在上面分析的 #加载并设置Bootstrapper
SpringApplicationRunListeners listeners = getRunListeners(args);
listeners.starting(bootstrapContext, this.mainApplicationClass); // 根据预先配置上下文对象,通知容器启动
try {
ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
// [2] 准备启动的环境,例如application.properties(系统环境变量,命令行参数等)
ConfigurableEnvironment environment = prepareEnvironment(listeners, bootstrapContext, applicationArguments);
configureIgnoreBeanInfo(environment);
// [3] 控制台打印SpringBoot的banner标识
Banner printedBanner = printBanner(environment);
// [4] 根据不同的环境创建不同的上下文容器
context = createApplicationContext();
context.setApplicationStartup(this.applicationStartup);
// [*] 初始化容器(在此没有标序号,因为它很重要)
prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner);
// [5] 刷新容器,调用容器的refresh方法,详情见spring源码
refreshContext(context);
// [6] 执行刷新容器后的后置方法,其中当前为空方法
afterRefresh(context, applicationArguments);
// [7] 停止启动计时
Duration timeTakenToStartup = Duration.ofNanos(System.nanoTime() - startTime);
if (this.logStartupInfo) {
/// 打印日志
new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), timeTakenToStartup);
}
//->发送[ApplicationStartedEvent]事件,标志spring容器已经刷新,此时所有的bean实例都已经加载完毕

listeners.started(context, timeTakenToStartup);
// [8] 调用ApplicationRunner和CommandLineRunner的run方法,实现spring容器启动后需要做的一些东西比如加载一些业务数据等
callRunners(context, applicationArguments);
}
catch (Throwable ex) { // 启动过程中发送异常事件,使用handleRunFailure来报告异常
handleRunFailure(context, ex, listeners);
throw new IllegalStateException(ex);
}
try {// ApplicationReadEvent事件标志着SpringApplication已经正在运行即已经成功启动,可以接收服务请求了
Duration timeTakenToReady = Duration.ofNanos(System.nanoTime() - startTime);
listeners.ready(context, timeTakenToReady);
}
catch (Throwable ex) {//若出现异常,此时仅仅报告异常,而不会发送任何事件
handleRunFailure(context, ex, null);
throw new IllegalStateException(ex);
}// [9] 最终返回容器
return context;
}
分析部分
加载监听器

#[1] #getRunListeners

1
2
3
4
5
6
private SpringApplicationRunListeners getRunListeners(String[] args) {
Class<?>[] types = new Class<?>[] { SpringApplication.class, String[].class };
return new SpringApplicationRunListeners(logger,
getSpringFactoriesInstances(SpringApplicationRunListener.class, types, this, args),
this.applicationStartup);
}

这个其实就是从#getSpringFactoriesInstances中获取spring.factories的全限名并加载SpringApplicationRunListener。这个就是SpringBoot的一系列的·生命周期监听器

Tips:如果我们也需要扩展,那么是不是也可以直接实现ApplicationRunListener就可以拿到一些事件的的信息

#[3] 控制台打印SpringBoot的banner标识

这个其实就是在启动的时候可以修改对应的启动图标

创建对应的context容器

#[4] 根据不同的环境创建不同的上下文容器

(当前SpringBoot版本已经切换到2.6.7了,与之前的可能会有所差别,例如在2.1.0中,#createApplicationContext的逻辑为通过switch枚举容器类型创建对应的容器)

1
2
3
protected ConfigurableApplicationContext createApplicationContext() {
return this.applicationContextFactory.create(this.webApplicationType);
}

FunctionInterface #ApplicationContextFactory

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
ApplicationContextFactory DEFAULT = (webApplicationType) -> {
try {
for (ApplicationContextFactory candidate : SpringFactoriesLoader
.loadFactories(ApplicationContextFactory.class, ApplicationContextFactory.class.getClassLoader())) {
ConfigurableApplicationContext context = candidate.create(webApplicationType);
if (context != null) {
return context;
}
}
return new AnnotationConfigApplicationContext();
}
catch (Exception ex) {
throw new IllegalStateException("Unable create a default ApplicationContext instance, "
+ "you may need a custom ApplicationContextFactory", ex);
}
};

现在通过函数式工厂方法定义接口模板实现

初始化容器

#[*] 初始化容器(#prepareContext)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
private void prepareContext(DefaultBootstrapContext bootstrapContext, ConfigurableApplicationContext context,
ConfigurableEnvironment environment, SpringApplicationRunListeners listeners,
ApplicationArguments applicationArguments, Banner printedBanner) {
// 将准备好的环境设置给上下文
context.setEnvironment(environment);
postProcessApplicationContext(context);
// 遍历所有的ApplicationContextInitializer的initialize()方法来对已经创建好的ApplicationContext进一步处理
applyInitializers(context);
// 调用SpringApplicationRunListeners的contextPrepared()方法来通知所有的监听者说:“我的容器已经准备好了”
listeners.contextPrepared(context);
bootstrapContext.close(context);
if (this.logStartupInfo) {
logStartupInfo(context.getParent() == null);
logStartupProfileInfo(context);
}
// Add boot specific singleton beans
ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
// 将springApplicationArguments注入到IOC容器
beanFactory.registerSingleton("springApplicationArguments", applicationArguments);
if (printedBanner != null) {
// 注册springBootBanner
beanFactory.registerSingleton("springBootBanner", printedBanner);
}
if (beanFactory instanceof AbstractAutowireCapableBeanFactory) {
((AbstractAutowireCapableBeanFactory) beanFactory).setAllowCircularReferences(this.allowCircularReferences);
if (beanFactory instanceof DefaultListableBeanFactory) {
((DefaultListableBeanFactory) beanFactory)
.setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
}
}
if (this.lazyInitialization) {
context.addBeanFactoryPostProcessor(new LazyInitializationBeanFactoryPostProcessor());
}
// Load the sources <-> 加载资源
Set<Object> sources = getAllSources();
Assert.notEmpty(sources, "Sources must not be empty");
load(context, sources.toArray(new Object[0]));
// 调用SpringApplicationRunListener的contextLoaded()方法,通知所有的监听者:ApplicationContext已经装载完毕
listeners.contextLoaded(context);
}

其中自动装配是在refresh的阶段实现的