『SpringBoot 源码分析』run() 方法执行流程:(2)刷新应用上下文-准备阶段
- 基于 2.2.9.RELEASE
- 问题:当方法进行了注释标记之后,springboot 又是怎么注入到容器中并创建类呢?
- 首先创建测试主程序
java
复制代码
package com.lagou;
@SpringBootApplication//标注在类上说明这个类是`SpringBoot`的主配置类
public class SpringBootMytestApplication{
public static void main(String[] args) {
SpringApplication.run(SpringBootMytestApplication.class, args);
}
}
- 创建测试 Controller
java
复制代码
package com.lagou.controller;
@RestController
public class TestController {
@RequestMapping("/test")
public String test(){
System.out.println("源码环境构建成功...");
return "源码环境构建成功";
}
}
准备阶段
- 当准备完成应用上下文环境,以及应用上下文以后,需要为应用上下文做个准备阶段,简单来说其实就是要配置应用上下文,把需要的类装配上
java
复制代码
public class SpringApplication {
...
public ConfigurableApplicationContext run(String... args) {
...
try {
// 将运行时参数封装
ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
// 构造应用上下文环境
ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);
// 处理需要忽略的 Bean
configureIgnoreBeanInfo(environment);
// 打印 banner
Banner printedBanner = printBanner(environment);
// 刷新应用上下文前的准备阶段
context = createApplicationContext();
// 实例化 SpringBootExceptionReporter.class,用来支持报告关于启动的错误
exceptionReporters = getSpringFactoriesInstances(SpringBootExceptionReporter.class,
new Class[] { ConfigurableApplicationContext.class }, context);
// 1. 刷新应用上下文前的准备阶段
prepareContext(context, environment, listeners, applicationArguments, printedBanner);
...
}
catch (Throwable ex) {
...
}
...
}
}
- 在对应用上下文进行处理时,主要执行了下面几步的装配
- 把上下文环境设置到应用上下文中
- 执行容器后置处理
- 把应用上下文交给 SpringApplication 初始化收集的 org.springframework.context.ApplicationContextInitializer 所有实现类进行初始化工作
- 利用 org.springframework.boot.context.event.EventPublishingRunListener 向 org.springframework.context.ApplicationListener 发布容器准备好事件
java
复制代码
public class SpringApplication {
...
// 完成属性设置 bean对象创建
private void prepareContext(ConfigurableApplicationContext context, ConfigurableEnvironment environment,
SpringApplicationRunListeners listeners, ApplicationArguments applicationArguments, Banner printedBanner) {
// 1. 设置容器环境
context.setEnvironment(environment);
// 2. 执行容器后置处理
postProcessApplicationContext(context);
// 3. 执行一些初始化器
applyInitializers(context);
// 4. 向各个监听器发送容器已经准备好的事件
listeners.contextPrepared(context);
...
}
}
- 执行容器后置处理:其实只是往 BeanFactory 添加了基础的转换器
java
复制代码
public class SpringApplication {
private BeanNameGenerator beanNameGenerator;
private ResourceLoader resourceLoader;
private boolean addConversionService = true;
...
protected void postProcessApplicationContext(ConfigurableApplicationContext context) {
if (this.beanNameGenerator != null) {
context.getBeanFactory().registerSingleton(AnnotationConfigUtils.CONFIGURATION_BEAN_NAME_GENERATOR,
this.beanNameGenerator);
}
if (this.resourceLoader != null) {
if (context instanceof GenericApplicationContext) {
((GenericApplicationContext) context).setResourceLoader(this.resourceLoader);
}
if (context instanceof DefaultResourceLoader) {
((DefaultResourceLoader) context).setClassLoader(this.resourceLoader.getClassLoader());
}
}
if (this.addConversionService) {
// 1. 设置了转换器,例如平时能把整数字符串转换为整形,设置转换器
context.getBeanFactory().setConversionService(ApplicationConversionService.getSharedInstance());
}
}
}
- 执行一些初始化器:就是遍历 org.springframework.context.ApplicationContextInitializer 执行 initialize() 方法
java
复制代码
public class SpringApplication {
...
protected void applyInitializers(ConfigurableApplicationContext context) {
for (ApplicationContextInitializer initializer : getInitializers()) {
Class<?> requiredType = GenericTypeResolver.resolveTypeArgument(initializer.getClass(),
ApplicationContextInitializer.class);
Assert.isInstanceOf(requiredType, context, "Unable to call initializer.");
initializer.initialize(context);
}
}
}
- 向各个监听器发送容器已经准备好的事件:就是 org.springframework.boot.context.event.EventPublishingRunListener 向 org.springframework.context.ApplicationListener 发布容器准备好事件
java
复制代码
public class SpringApplication {
...
// 1. 当 ApplicationContext 构建完成时,该方法被调用
void contextPrepared(ConfigurableApplicationContext context) {
for (SpringApplicationRunListener listener : this.listeners) {
listener.contextPrepared(context);
}
}
}
- 发布完监听之后,从上下文中获取 IOC 工厂,并设置允许 bean 定义被覆盖参数
java
复制代码
public class SpringApplication {
...
// 完成属性设置 bean 对象创建
private void prepareContext(ConfigurableApplicationContext context, ConfigurableEnvironment environment,
SpringApplicationRunListeners listeners, ApplicationArguments applicationArguments, Banner printedBanner) {
// 设置容器环境
context.setEnvironment(environment);
// 执行容器后置处理
postProcessApplicationContext(context);
// 执行一些初始化器
applyInitializers(context);
// 向各个监听器发送容器已经准备好的事件
listeners.contextPrepared(context);
if (this.logStartupInfo) {
logStartupInfo(context.getParent() == null);
logStartupProfileInfo(context);
}
// 1. 获取 IOC 容器
ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
// 将 main() 函数中的 args 参数封装成单例 Bean,注册进容器
beanFactory.registerSingleton("springApplicationArguments", applicationArguments);
if (printedBanner != null) {
// 将 printedBanner 也封装成单例,注册进容器
beanFactory.registerSingleton("springBootBanner", printedBanner);
}
// 2. 设置允许 bean 定义被覆盖参数
if (beanFactory instanceof DefaultListableBeanFactory) {
((DefaultListableBeanFactory) beanFactory)
.setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
}
...
}
}
- 然后加载启动类,并将启动类注入到容器当中,然后发布容器已加载事件
java
复制代码
public class SpringApplication {
...
// 完成属性设置 bean 对象创建
private void prepareContext(ConfigurableApplicationContext context, ConfigurableEnvironment environment,
SpringApplicationRunListeners listeners, ApplicationArguments applicationArguments, Banner printedBanner) {
// 设置容器环境
context.setEnvironment(environment);
// 执行容器后置处理
postProcessApplicationContext(context);
// 执行一些初始化器
applyInitializers(context);
// 向各个监听器发送容器已经准备好的事件
listeners.contextPrepared(context);
if (this.logStartupInfo) {
logStartupInfo(context.getParent() == null);
logStartupProfileInfo(context);
}
// 获取 IOC 容器
ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
// 将 main() 函数中的 args 参数封装成单例 Bean,注册进容器
beanFactory.registerSingleton("springApplicationArguments", applicationArguments);
if (printedBanner != null) {
// 将 printedBanner 也封装成单例,注册进容器
beanFactory.registerSingleton("springBootBanner", printedBanner);
}
// 设置允许 bean 定义被覆盖参数
if (beanFactory instanceof DefaultListableBeanFactory) {
((DefaultListableBeanFactory) beanFactory)
.setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
}
if (this.lazyInitialization) { // 是否需要进行懒加载,这里不是
context.addBeanFactoryPostProcessor(new LazyInitializationBeanFactoryPostProcessor());
}
// 1. 加载源,这里拿到的是主类,com.lagou.SpringBootMytestApplication
Set<Object> sources = getAllSources();
Assert.notEmpty(sources, "Sources must not be empty");
// 2. 加载我们的启动类,将启动类注入容器 重点关注
load(context, sources.toArray(new Object[0]));// 取出第一个元素,就是主类,要先实例化主类,灌入容器中
// 3. 发布容器已加载事件
listeners.contextLoaded(context);
}
}
- 其中将启动类注入到容器当中是比较关键的一步,首先先把 ApplicationContext 转换成 BeanDefinitionRegistry,然后创建 bean 定义加载器
java
复制代码
public class SpringApplication {
...
protected void load(ApplicationContext context, Object[] sources) {
if (logger.isDebugEnabled()) {
logger.debug("Loading source " + StringUtils.arrayToCommaDelimitedString(sources));
}
// 2. 创建 BeanDefinitionLoader
BeanDefinitionLoader loader = createBeanDefinitionLoader(getBeanDefinitionRegistry(context), sources);
...
}
private BeanDefinitionRegistry getBeanDefinitionRegistry(ApplicationContext context) {
// 1. 将 ApplicationContext 转换成 BeanDefinitionRegistry
if (context instanceof BeanDefinitionRegistry) {
return (BeanDefinitionRegistry) context;
}
if (context instanceof AbstractApplicationContext) {
return (BeanDefinitionRegistry) ((AbstractApplicationContext) context).getBeanFactory();
}
throw new IllegalStateException("Could not locate BeanDefinitionRegistry");
}
}
- 创建 BeanDefinitionLoader 主要是把 BeanDefinitionRegistry 以及主类的 sources 进行赋值初始化
java
复制代码
public class SpringApplication {
private final Object[] sources;
private final AnnotatedBeanDefinitionReader annotatedReader;
private final XmlBeanDefinitionReader xmlReader;
private BeanDefinitionReader groovyReader;
private final ClassPathBeanDefinitionScanner scanner;
private ResourceLoader resourceLoader;
...
protected BeanDefinitionLoader createBeanDefinitionLoader(BeanDefinitionRegistry registry, Object[] sources) {
// 1. 创建 bean 定义加载器
return new BeanDefinitionLoader(registry, sources);
}
BeanDefinitionLoader(BeanDefinitionRegistry registry, Object... sources) {
// 其中,sources 就是主类 com.lagou.SpringBootMytestApplication
Assert.notNull(registry, "Registry must not be null");
Assert.notEmpty(sources, "Sources must not be empty");
this.sources = sources;
// 2. 注解形式的 Bean 定义读取器 比如:@Configuration @Bean @Component @Controller @Service等等
this.annotatedReader = new AnnotatedBeanDefinitionReader(registry);
// 3. XML 形式的 Bean 定义读取器
this.xmlReader = new XmlBeanDefinitionReader(registry);
if (isGroovyPresent()) {
this.groovyReader = new GroovyBeanDefinitionReader(registry);
}
// 4. 类路径扫描器
this.scanner = new ClassPathBeanDefinitionScanner(registry);
// 5. 扫描器添加排除过滤器
this.scanner.addExcludeFilter(new ClassExcludeFilter(sources));
}
}
- 创建 BeanDefinitionLoader 成功后,就可以开始执行 load(),这里主要是先把主类注册到 IOC 容器中去
java
复制代码
public class SpringApplication {
private BeanNameGenerator beanNameGenerator;
...
protected void load(ApplicationContext context, Object[] sources) {
if (logger.isDebugEnabled()) {
logger.debug("Loading source " + StringUtils.arrayToCommaDelimitedString(sources));
}
// 创建 BeanDefinitionLoader
BeanDefinitionLoader loader = createBeanDefinitionLoader(getBeanDefinitionRegistry(context), sources);
if (this.beanNameGenerator != null) {
loader.setBeanNameGenerator(this.beanNameGenerator);
}
if (this.resourceLoader != null) {
loader.setResourceLoader(this.resourceLoader);
}
if (this.environment != null) {
loader.setEnvironment(this.environment);
}
// 1. 执行 load()
loader.load();
}
}
- 其中 load() 通过 AnnotatedBeanDefinitionReader 将主类 source 注册进 beanDefinitionMap 中
java
复制代码
class BeanDefinitionLoader {
private final AnnotatedBeanDefinitionReader annotatedReader;
...
int load() {
int count = 0;
for (Object source : this.sources) {
count += load(source);
}
return count;
}
// 根据加载不同类型调用不同的方法
private int load(Object source) {
Assert.notNull(source, "Source must not be null");
// 1. 从 Class 加载
if (source instanceof Class<?>) {
return load((Class<?>) source);
}
...
}
private int load(Class<?> source) {
// source 就是 class com.lagou.SpringBootMytestApplication
if (isGroovyPresent() && GroovyBeanDefinitionSource.class.isAssignableFrom(source)) {
// Any GroovyLoaders added in beans{} DSL can contribute beans here
GroovyBeanDefinitionSource loader = BeanUtils.instantiateClass(source, GroovyBeanDefinitionSource.class);
load(loader);
}
if (isComponent(source)) { // 判断方法有没有标记 Component 注解
// 1. 将启动类的 BeanDefinition 注册进 beanDefinitionMap
this.annotatedReader.register(source);
return 1;
}
return 0;
}
}
- 调用 register() 方法时,真正会传到 doRegisterBean() 进行执行。首先会把主类转换成 AnnotatedGenericBeanDefinition ,然后获取主类的名称,把名称和 AnnotatedGenericBeanDefinition 封装成 BeanDefinitionHolder 后,注册到上下文中
java
复制代码
public class AnnotatedBeanDefinitionReader {
...
public void register(Class<?>... componentClasses) {
for (Class<?> componentClass : componentClasses) {
registerBean(componentClass);
}
}
public void registerBean(Class<?> beanClass) {
doRegisterBean(beanClass, null, null, null, null);
}
private <T> void doRegisterBean(Class<T> beanClass, @Nullable String name,
@Nullable Class<? extends Annotation>[] qualifiers, @Nullable Supplier<T> supplier,
@Nullable BeanDefinitionCustomizer[] customizers) {
// 1. 把主类转换成 AnnotatedGenericBeanDefinition,其中 beanClass 为 com.lagou.SpringBootMytestApplication
AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(beanClass);
if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) {
return;
}
abd.setInstanceSupplier(supplier);
ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);
abd.setScope(scopeMetadata.getScopeName());
// 2. 获取类名 springBootMytestApplication
String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry));
AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);
if (qualifiers != null) {
for (Class<? extends Annotation> qualifier : qualifiers) {
if (Primary.class == qualifier) {
abd.setPrimary(true);
}
else if (Lazy.class == qualifier) {
abd.setLazyInit(true);
}
else {
abd.addQualifier(new AutowireCandidateQualifier(qualifier));
}
}
}
if (customizers != null) {
for (BeanDefinitionCustomizer customizer : customizers) {
customizer.customize(abd);
}
}
// 3. 封装成 BeanDefinitionHolder
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);
definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
// 4. 注册到容器中
BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
}
}
- 注册到容器中,简单而言就是调用 BeanDefinitionRegistry 把 BeanDefinitionHolder 的 name 和 AnnotatedGenericBeanDefinition 装配进去
java
复制代码
public abstract class BeanDefinitionReaderUtils {
...
public static void registerBeanDefinition(BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry) throws BeanDefinitionStoreException {
// 1. 获取名称 springBootMytestApplication
String beanName = definitionHolder.getBeanName();
// 2. 注册到 IOC 容器中
registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());
String[] aliases = definitionHolder.getAliases();
if (aliases != null) {
String[] var4 = aliases;
int var5 = aliases.length;
for(int var6 = 0; var6 < var5; ++var6) {
String alias = var4[var6];
registry.registerAlias(beanName, alias);
}
}
}
}
- 最后会把 name 和 AnnotatedGenericBeanDefinition 存入到 beanDefinitionMap 中
java
复制代码
public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable {
...
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) throws BeanDefinitionStoreException {
Assert.hasText(beanName, "Bean name must not be empty");
Assert.notNull(beanDefinition, "BeanDefinition must not be null");
// 1. 先校验 beanDefinition 是否合法
if (beanDefinition instanceof AbstractBeanDefinition) {
try {
((AbstractBeanDefinition)beanDefinition).validate();
} catch (BeanDefinitionValidationException var8) {
throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName, "Validation of bean definition failed", var8);
}
}
BeanDefinition existingDefinition = (BeanDefinition)this.beanDefinitionMap.get(beanName);
if (existingDefinition != null) {
if (!this.isAllowBeanDefinitionOverriding()) {
throw new BeanDefinitionOverrideException(beanName, beanDefinition, existingDefinition);
}
if (existingDefinition.getRole() < beanDefinition.getRole()) {
if (this.logger.isInfoEnabled()) {
this.logger.info("Overriding user-defined bean definition for bean '" + beanName + "' with a framework-generated bean definition: replacing [" + existingDefinition + "] with [" + beanDefinition + "]");
}
} else if (!beanDefinition.equals(existingDefinition)) {
if (this.logger.isDebugEnabled()) {
this.logger.debug("Overriding bean definition for bean '" + beanName + "' with a different definition: replacing [" + existingDefinition + "] with [" + beanDefinition + "]");
}
} else if (this.logger.isTraceEnabled()) {
this.logger.trace("Overriding bean definition for bean '" + beanName + "' with an equivalent definition: replacing [" + existingDefinition + "] with [" + beanDefinition + "]");
}
this.beanDefinitionMap.put(beanName, beanDefinition);
} else {
if (this.hasBeanCreationStarted()) {
synchronized(this.beanDefinitionMap) {
this.beanDefinitionMap.put(beanName, beanDefinition);
List<String> updatedDefinitions = new ArrayList(this.beanDefinitionNames.size() + 1);
updatedDefinitions.addAll(this.beanDefinitionNames);
updatedDefinitions.add(beanName);
this.beanDefinitionNames = updatedDefinitions;
this.removeManualSingletonName(beanName);
}
} else {
// 2. 再把 beanDefinition 放到 beanDefinitionMap 中
this.beanDefinitionMap.put(beanName, beanDefinition);
this.beanDefinitionNames.add(beanName);
this.removeManualSingletonName(beanName);
}
this.frozenBeanDefinitionNames = null;
}
if (existingDefinition == null && !this.containsSingleton(beanName)) {
if (this.isConfigurationFrozen()) {
this.clearByTypeCache();
}
} else {
this.resetBeanDefinition(beanName);
}
}
}
- 总结