传送门
SpringMVC的源码解析(精品)
Spring6的源码解析(精品)
SpringBoot3框架(精品)
MyBatis框架(精品)
MyBatis-Plus
SpringDataJPA
SpringCloudNetflix
SpringCloudAlibaba(精品)
Shiro
SpringSecurity
java的LOG日志框架
Activiti(敬请期待)
JDK8新特性
JDK9新特性
JDK10新特性
JDK11新特性
JDK12新特性
JDK13新特性
JDK14新特性
JDK15新特性
JDK16新特性
JDK17新特性
JDK18新特性
JDK19新特性
JDK20新特性
JDK21新特性
其他技术文章传送门入口
一、前言
由于面试问到的比较多,而且做java开发这块还是需要真正掌握的。
现有笔记尚硅谷雷锋阳老师的:SpringBoot3全栈指南,是我目前见过的最好笔记了。
参考视频尚硅谷雷锋阳老师的:SpringBoot零基础教程,面试&加薪必会,视频是24小时31分钟的高质量教程。
参考代码:https://gitee.com/leifengyang/spring-boot-3
本文以SpringBoot3.1.2中Spring对应版本是6.0.11为例。
下面文章不定期更新中…
二、面试回答总结
最经典的20个Spring Boot面试题,95%以上会被问到,不服来战
三、源码解析(简单版)
1、SpringBoot创建Spring上下文
10和11行代码的区别,10行传了args参数,java -jar xxx.jar --k1=v1这种的时候,就是有效果的,否则像11行那样,是没有效果的。
我们来看一个SpringBoot3的启动类案例,并跟着这个案例深入
@SpringBootApplication
public class JdkNewFeaturesDemoApplication {
public static void main(String[] args) {
SpringApplication.run(JdkNewFeaturesDemoApplication.class, args);// 断点进入run方法
}
}
public static ConfigurableApplicationContext run(Class<?> primarySource, String... args) {
return run(new Class<?>[] { primarySource }, args);// 断点进入run方法
}
public static ConfigurableApplicationContext run(Class<?>[] primarySources, String[] args) {
return new SpringApplication(primarySources).run(args);// 分两部分,断点进入第一部分new,断点进入第二部分run
}
ConfigurableApplicationContext 类是容器上下文,但是不是最终容器上下文,SpringApplication非Spring容器上下文。
一般最终Spring容器上下文是AnnotationConfigServletWebServerApplicationContext。
我们断点进入第一部分new的代码
public SpringApplication(Class<?>... primarySources) {
this(null, primarySources);
}
/**
* Create a new {@link SpringApplication} instance. The application context will load
* beans from the specified primary sources (see {@link SpringApplication class-level}
* documentation for details). The instance can be customized before calling
* {@link #run(String...)}.
* @param resourceLoader the resource loader to use
* @param primarySources the primary bean sources
* @see #run(Class, String[])
* @see #setSources(Set)
*/
@SuppressWarnings({ "unchecked", "rawtypes" })
public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
this.resourceLoader = resourceLoader;// 资源加载器
Assert.notNull(primarySources, "PrimarySources must not be null");
this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));// primarySources启动类
this.webApplicationType = WebApplicationType.deduceFromClasspath();// 判断web的上下文是servlet上下文还是reactive上下文,reactive是响应式编程(webflux),当然SpringBoot默认是servlet
this.bootstrapRegistryInitializers = new ArrayList<>(
getSpringFactoriesInstances(BootstrapRegistryInitializer.class));
setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));//(断点进入设置初始化器) 设置初始化器,就是将实现了ApplicationContextInitializer接口的实现类实例化并缓存一下,这边会加载到META-INF/spring.factories(该文件就是自动装配。主要是接口和实现类的对应,一个接口有多个实现类值,Key-Values的对应)
setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));// 设置监听器,将实现了ApplicationListener接口的实现类实例化
this.mainApplicationClass = deduceMainApplicationClass();// 调用main方法的类返回出来赋值到这里,目的是解析这个类以及类上的注解。
}
我们断点进入设置初始化器
setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class))
private <T> List<T> getSpringFactoriesInstances(Class<T> type) {
return getSpringFactoriesInstances(type, null);// 断点持续进入
}
private <T> List<T> getSpringFactoriesInstances(Class<T> type, ArgumentResolver argumentResolver) {
return SpringFactoriesLoader.forDefaultResourceLocation(getClassLoader()).load(type, argumentResolver);
// 第一部分forDefaultResourceLocation这边会加载到META-INF/spring.factories(该文件就是自动装配。主要是接口和实现类的对应,一个接口有多个实现类值,Key-Values的对应)
// 第二部分load,断点持续进入
}
public <T> List<T> load(Class<T> factoryType, @Nullable ArgumentResolver argumentResolver,
@Nullable FailureHandler failureHandler) {
Assert.notNull(factoryType, "'factoryType' must not be null");
List<String> implementationNames = loadFactoryNames(factoryType);// 加载到对应类的实现名字,也就是实现了ApplicationContextInitializer接口的实现类
logger.trace(LogMessage.format("Loaded [%s] names: %s", factoryType.getName(), implementationNames));
List<T> result = new ArrayList<>(implementationNames.size());
FailureHandler failureHandlerToUse = (failureHandler != null) ? failureHandler : THROWING_FAILURE_HANDLER;
for (String implementationName : implementationNames) {
// 将这些实现名字做一个实例化
T factory = instantiateFactory(implementationName, factoryType, argumentResolver, failureHandlerToUse);
if (factory != null) {
result.add(factory);
}
}
AnnotationAwareOrderComparator.sort(result);
return result;// 这类比一个缓存,以后获取的时候方便
}
我们返回到开始,断点进入第二部分run的代码
public ConfigurableApplicationContext run(String... args) {
long startTime = System.nanoTime();
DefaultBootstrapContext bootstrapContext = createBootstrapContext();// 创建一个启动上下文,非Spring容器上下文,做一些启动方面相关的处理,只是在boot工程启动时间的临时上下文,内置多播器
ConfigurableApplicationContext context = null;
// 根据系统变量java.awt.headless的值来设置java.headless.mode,缺省值是true,
// 在系统可能缺少显示设备、键盘或鼠标这些外设的情况下可以使用该模式。
// 默认为true,因为大部分的boot项目都不需要外设交互,一旦启动成功就不需要操作。
configureHeadlessProperty();
SpringApplicationRunListeners listeners = getRunListeners(args);// 拿到一些监听器
listeners.starting(bootstrapContext, this.mainApplicationClass);// 监听器开始工作,发布ApplicationStartingEvent事件
try {
ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);// 获取命令行参数
ConfigurableEnvironment environment = prepareEnvironment(listeners, bootstrapContext, applicationArguments);// 准备环境
Banner printedBanner = printBanner(environment);// 打印banner
// 【核心】创建一个Spring上下文,不执行refresh方法,一般最终Spring容器上下文是AnnotationConfigServletWebServerApplicationContext
context = createApplicationContext();// 断点进入创建Spring容器上下文
context.setApplicationStartup(this.applicationStartup);// 设置记录步骤的记录器
// 这里会将一些早期事件注册给多播器,并发布一个事件
// 【核心】准备上下文
prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner);// 断点进入准备上下文
// 【核心】刷新容器,真正执行了refresh方法
refreshContext(context);// 断点进入刷新容器
afterRefresh(context, applicationArguments);// 刷新后处理
Duration timeTakenToStartup = Duration.ofNanos(System.nanoTime() - startTime);
if (this.logStartupInfo) {
new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), timeTakenToStartup);
}
listeners.started(context, timeTakenToStartup);// 广播启动完成事件
callRunners(context, applicationArguments);// 执行所有的runner,runner机制,实现对应接口,在SpringBoot启动后能做一些初始化工作,比如Redis预热
}
catch (Throwable ex) {
if (ex instanceof AbandonedRunException) {
throw ex;
}
handleRunFailure(context, ex, listeners);
throw new IllegalStateException(ex);
}
try {
if (context.isRunning()) {
Duration timeTakenToReady = Duration.ofNanos(System.nanoTime() - startTime);
listeners.ready(context, timeTakenToReady);
}
}
catch (Throwable ex) {
if (ex instanceof AbandonedRunException) {
throw ex;
}
handleRunFailure(context, ex, null);
throw new IllegalStateException(ex);
}
return context;
}
我们断点进入context = createApplicationContext();// 断点进入创建Spring容器上下文
protected ConfigurableApplicationContext createApplicationContext() {
return this.applicationContextFactory.create(this.webApplicationType);// DefaultApplicationContextFactory是成员变量就赋值好的默认上下文工厂,webApplicationType类型是SERVLET(根据配置决定的)
}
// 断点进入DefaultApplicationContextFactory的create方法
// 实际上走的ServletWebServerApplicationContextFactory的create方法(SpringBoot默认是servlet,所以一般是走这个实现类的create方法)
@Override
public ConfigurableApplicationContext create(WebApplicationType webApplicationType) {
try {
return getFromSpringFactories(webApplicationType, ApplicationContextFactory::create,
this::createDefaultApplicationContext);// 断点进入getFromSpringFactories
}
catch (Exception ex) {
throw new IllegalStateException("Unable create a default ApplicationContext instance, "
+ "you may need a custom ApplicationContextFactory", ex);
}
}
// 断点进入getFromSpringFactories方法
private <T> T getFromSpringFactories(WebApplicationType webApplicationType,
BiFunction<ApplicationContextFactory, WebApplicationType, T> action, Supplier<T> defaultResult) {
// 循环ApplicationContextFactory的实现类,一般有三个,在spring.factories中可以看到(不同jar包这个文件内容不一样)
// DefaultApplicationContextFactory、ReactiveWebServerApplicationContextFactory、ServletWebServerApplicationContextFactory
for (ApplicationContextFactory candidate : SpringFactoriesLoader.loadFactories(ApplicationContextFactory.class,
getClass().getClassLoader())) {
T result = action.apply(candidate, webApplicationType);// 判断哪个工厂能满足条件,这边一般返回了子类,返回的就是最终的Spring容器上下文,比如SpringBoot默认是servlet而非reactive,返回的就是AnnotationConfigServletWebServerApplicationContext
if (result != null) {
return result;
}
}
return (defaultResult != null) ? defaultResult.get() : null;
}
我们返回到上一级ConfigurableApplicationContext的run方法代码中, 断点进入准备上下文
prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner);
private void prepareContext(DefaultBootstrapContext bootstrapContext, ConfigurableApplicationContext context,
ConfigurableEnvironment environment, SpringApplicationRunListeners listeners,
ApplicationArguments applicationArguments, Banner printedBanner) {
context.setEnvironment(environment);// 设置环境
postProcessApplicationContext(context);// 上下文的后置处理,设置了消息转化器
addAotGeneratedInitializerIfNecessary(this.initializers);// aot相关
applyInitializers(context);// 调用之前设置的初始化器,执行一些方法
listeners.contextPrepared(context);// ApplicationcontextInitializedEvent事件
bootstrapContext.close(context);// 关闭启动上下文
if (this.logStartupInfo) {
logStartupInfo(context.getParent() == null);
logStartupProfileInfo(context);
}
// Add boot specific singleton beans
ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();// 从上下文拿到默认的bean工厂,下面给工厂设置一些参数
beanFactory.registerSingleton("springApplicationArguments", applicationArguments);
if (printedBanner != null) {
beanFactory.registerSingleton("springBootBanner", printedBanner);
}
if (beanFactory instanceof AbstractAutowireCapableBeanFactory autowireCapableBeanFactory) {
autowireCapableBeanFactory.setAllowCircularReferences(this.allowCircularReferences);// 设置是否允许循环引用,默认是没有开启循环引用的。
if (beanFactory instanceof DefaultListableBeanFactory listableBeanFactory) {
listableBeanFactory.setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);// 设置BeanDefinition是否可以被覆盖,默认false没有开启。
}
}
if (this.lazyInitialization) {
context.addBeanFactoryPostProcessor(new LazyInitializationBeanFactoryPostProcessor());
}
context.addBeanFactoryPostProcessor(new PropertySourceOrderingBeanFactoryPostProcessor(context));// 添加一些BeanFactory的后置处理器,PropertySourceOrder是优先级高的那批后置处理器。
if (!AotDetector.useGeneratedArtifacts()) {
// Load the sources
Set<Object> sources = getAllSources();// 加载资源,BeanDefinition
Assert.notEmpty(sources, "Sources must not be empty");
load(context, sources.toArray(new Object[0]));
}
listeners.contextLoaded(context);// 发布上下文加载相关的事件
}
我们返回到上一级ConfigurableApplicationContext的run方法代码中, 断点进入
refreshContext(context);// 断点进入刷新容器
private void refreshContext(ConfigurableApplicationContext context) {
if (this.registerShutdownHook) {
shutdownHook.registerApplicationContext(context);// shutdownHook是钩子
}
refresh(context);// 断点持续进入
}
protected void refresh(ConfigurableApplicationContext applicationContext) {
applicationContext.refresh();// 断点持续进入
}
// ServletWebServerApplicationContext的refresh方法(servlet进入这个)
@Override
public final void refresh() throws BeansException, IllegalStateException {
try {
super.refresh();// 就会调用到父类的AbstractApplicationContext的refresh方法,真正刷新。父类的refresh方法中预留的让子类调用的扩展点,有被SpringBoot重写。比如refresh方法里面的onRefresh方法,就被子类启动了tomcat。
}
catch (RuntimeException ex) {// 抛异常,如果SpringBoot上下文启动失败
WebServer webServer = this.webServer;// 能获取到webServer
if (webServer != null) {
webServer.stop();// 会将webServer停止掉
}
throw ex;
}
}
2、SpringBoot的自动装配
我们回到最开始,持续进入看@SpringBootApplication注解,可以看到重要的@EnableAutoConfiguration注解
@SpringBootApplication// 持续点进去
public class JdkNewFeaturesDemoApplication {
public static void main(String[] args) {
SpringApplication.run(JdkNewFeaturesDemoApplication.class, args);// 断点进入run方法
}
}
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)// 点进去,引入一个Selector,这个Selector返回的字符串数组,里面所有的全限定名称bean都会加载到Spring容器中。
public @interface EnableAutoConfiguration {
/**
* Environment property that can be used to override when auto-configuration is
* enabled.
*/
String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";
/**
* Exclude specific auto-configuration classes such that they will never be applied.
* @return the classes to exclude
*/
Class<?>[] exclude() default {};
/**
* Exclude specific auto-configuration class names such that they will never be
* applied.
* @return the class names to exclude
* @since 1.3.0
*/
String[] excludeName() default {};
}
AutoConfigurationImportSelector点进去可以看到重要的selectImports方法
@Override
public String[] selectImports(AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotationMetadata)) {
return NO_IMPORTS;
}
// 【核心】获取到自动装配的健值对
AutoConfigurationEntry autoConfigurationEntry = getAutoConfigurationEntry(annotationMetadata);// 断点进入
// 将键值对里面的Configurations拿到,返回字符串数组,进而加载到Spring容器中。
return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
}
// 断点进入
protected AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotationMetadata)) {
return EMPTY_ENTRY;
}
// annotationMetadata就是启动类com.zt.JdkNewFeaturesDemoApplication相关的一些东西,是元数据
AnnotationAttributes attributes = getAttributes(annotationMetadata);// attributes为exclude和excludeName,后面主要用于排除一些bean
// 【核心】获取候选的配置类,SpringBoot3.1.2版本有146个XxxAutoConfiguration自动装配配置类。
List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);// 断点进入
// 进行筛选去重过滤
configurations = removeDuplicates(configurations);
Set<String> exclusions = getExclusions(annotationMetadata, attributes);
checkExcludedClasses(configurations, exclusions);
configurations.removeAll(exclusions);
configurations = getConfigurationClassFilter().filter(configurations);// 最后得到25个
fireAutoConfigurationImportEvents(configurations, exclusions);
return new AutoConfigurationEntry(configurations, exclusions);// key是25个List<String>,value是空的Set<String>
}
// 断点进入
protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
// 【核心】加载AutoConfiguration.class作为key的所有资源
List<String> configurations = ImportCandidates.load(AutoConfiguration.class, getBeanClassLoader())// 断点进入
.getCandidates();
Assert.notEmpty(configurations,
"No auto configuration classes found in "
+ "META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports. If you "
+ "are using a custom packaging, make sure that file is correct.");
return configurations;
}
断点进入
List configurations = ImportCandidates.load(AutoConfiguration.class, getBeanClassLoader())
【核心】加载AutoConfiguration.class作为key的所有资源
// annotation这个就是AutoConfiguration.class
public static ImportCandidates load(Class<?> annotation, ClassLoader classLoader) {
Assert.notNull(annotation, "'annotation' must not be null");
ClassLoader classLoaderToUse = decideClassloader(classLoader);
// 格式化LOCATION,格式化后的字符串为
// META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
// 这个imports文件就在自动装配spring-boot-autoconfigure的jar包里面,路径就是上面路径
// 里面是Spring支持的所有的自动装配相关的配置类,注意都是XxxAutoConfiguration配置类
String location = String.format(LOCATION, annotation.getName());
Enumeration<URL> urls = findUrlsInClasspath(classLoaderToUse, location);
List<String> importCandidates = new ArrayList<>();
while (urls.hasMoreElements()) {
URL url = urls.nextElement();
importCandidates.addAll(readCandidateConfigurations(url));
}
return new ImportCandidates(importCandidates);
}
难点:
SpringBoot3.1.2版本有146个XxxAutoConfiguration自动装配配置类是在Spring的refresh方法中哪一步加载进入的呢?
答案是refresh的12个方法中第5个方法:
方法5之前beanFactory对象的beanDefinitionMap属性只有6个,也就是有6个基本的BeanDefinition;
invokeBeanFactoryPostProcessors(beanFactory);// 5、执行BeanFactoryPostProcessor的方法;
方法5之后,beanDefinitionMap就有146个了。
@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");// 记录每一步执行的工具类
// Prepare this context for refreshing.
prepareRefresh();// 1、准备刷新容器上下文
// Tell the subclass to refresh the internal bean factory.
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();// 2、获取BeanFactory;默认实现是DefaultListableBeanFactory,在创建容器的时候创建的,beanFactory 里面有个beanDefinitionMap属性,存放BeanDefinition。
// Prepare the bean factory for use in this context.
prepareBeanFactory(beanFactory);// 3、BeanFactory的预准备工作(BeanFactory进行一些设置,比如context的类加载器,BeanPostProcessor和XXXAware自动装配等)
try {
// Allows post-processing of the bean factory in context subclasses.
postProcessBeanFactory(beanFactory);// 4、BeanFactory准备工作完成后进行的后置处理工作(留给子类实现,空方法)
StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");
// Invoke factory processors registered as beans in the context.
invokeBeanFactoryPostProcessors(beanFactory);// 5、执行BeanFactoryPostProcessor的方法;
// Register bean processors that intercept bean creation.
registerBeanPostProcessors(beanFactory);// 6、注册BeanPostProcessor(Bean的后置处理器),在创建bean的前后等执行
beanPostProcess.end();
// Initialize message source for this context.
initMessageSource();// 7、初始化MessageSource组件(做国际化功能;消息绑定,消息解析);
// Initialize event multicaster for this context.
initApplicationEventMulticaster(); // 8、初始化事件多播器
// Initialize other special beans in specific context subclasses.
onRefresh();// 9、子类重写这个方法,在容器刷新的时候可以自定义逻辑;如创建Tomcat,Jetty等WEB服务器
// Check for listener beans and register them.
registerListeners(); // 10、注册应用的监听器。就是注册实现了ApplicationListener接口的监听器bean,这些监听器是注册到ApplicationEventMulticaster中的
// Instantiate all remaining (non-lazy-init) singletons.
finishBeanFactoryInitialization(beanFactory);// 11、实例化所有的非懒加载单例bean(最最核心方法)
// Last step: publish corresponding event.
finishRefresh();// 12、完成context的刷新。主要是调用LifecycleProcessor的onRefresh()方法,并且发布事件(ContextRefreshedEvent)
}
catch (BeansException ex) {
if (logger.isWarnEnabled()) {
logger.warn("Exception encountered during context initialization - " +
"cancelling refresh attempt: " + ex);
}
// Destroy already created singletons to avoid dangling resources.
destroyBeans();
// Reset 'active' flag.
cancelRefresh(ex);
// Propagate exception to caller.
throw ex;
}
finally {
// Reset common introspection caches in Spring's core, since we
// might not ever need metadata for singleton beans anymore...
resetCommonCaches();
contextRefresh.end();
}
}
}
一路判断invokeBeanFactoryPostProcessors(beanFactory)中哪一行代码导致的beanDefinitionMap突然变多,会发现
ConfigurationClassPostProcessor这个processor是优先级最高的被执行的processor(实现了PriorityOrdered接口)。
在我Spring6源码解析的文章中有详细的讲解。(见传送门)
private static void invokeBeanDefinitionRegistryPostProcessors(
Collection<? extends BeanDefinitionRegistryPostProcessor> postProcessors, BeanDefinitionRegistry registry, ApplicationStartup applicationStartup) {
// for循环第一个就是ConfigurationClassPostProcessor
for (BeanDefinitionRegistryPostProcessor postProcessor : postProcessors) {
StartupStep postProcessBeanDefRegistry = applicationStartup.start("spring.context.beandef-registry.post-process")
.tag("postProcessor", postProcessor::toString);
// ConfigurationClassPostProcessor类里面的postProcessBeanDefinitionRegistry方法执行后,
// 这里就将剩余的BeanDefinition(XxxAutoConfiguration)注册进入了,beanDefinitionMap就有146个了
// 有了XxxAutoConfiguration这些BeanDefinition,其余的通过条件判断注解等等条件,普通的BeanDefinition也就注册进去了
postProcessor.postProcessBeanDefinitionRegistry(registry);
postProcessBeanDefRegistry.end();
}
}
接下来就是看ConfigurationClassPostProcessor何时进入的容器,ConfigurationClassPostProcessor是在最初始的beanDefinitionMap的6个里面的。
接下来我们就要看SpringBoot的run方法来分析了
其中context = createApplicationContext();// 【核心】创建一个Spring上下文,不执行refresh方法
我们仔细回顾一下这一步
public ConfigurableApplicationContext run(String... args) {
long startTime = System.nanoTime();
DefaultBootstrapContext bootstrapContext = createBootstrapContext();// 创建一个启动上下文,非Spring容器上下文,做一些启动方面相关的处理,只是在boot工程启动时间的临时上下文,内置多播器
ConfigurableApplicationContext context = null;
// 根据系统变量java.awt.headless的值来设置java.headless.mode,缺省值是true,
// 在系统可能缺少显示设备、键盘或鼠标这些外设的情况下可以使用该模式。
// 默认为true,因为大部分的boot项目都不需要外设交互,一旦启动成功就不需要操作。
configureHeadlessProperty();
SpringApplicationRunListeners listeners = getRunListeners(args);// 拿到一些监听器
listeners.starting(bootstrapContext, this.mainApplicationClass);// 监听器开始工作,发布ApplicationStartingEvent事件
try {
ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);// 获取命令行参数
ConfigurableEnvironment environment = prepareEnvironment(listeners, bootstrapContext, applicationArguments);// 准备环境
Banner printedBanner = printBanner(environment);// 打印banner
// 【核心】创建一个Spring上下文,不执行refresh方法,一般最终Spring容器上下文是AnnotationConfigServletWebServerApplicationContext
context = createApplicationContext();// 断点进入创建Spring容器上下文
context.setApplicationStartup(this.applicationStartup);// 设置记录步骤的记录器
// 这里会将一些早期事件注册给多播器,并发布一个事件
// 【核心】准备上下文
prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner);// 断点进入准备上下文
// 【核心】刷新容器,真正执行了refresh方法
refreshContext(context);// 断点进入刷新容器
afterRefresh(context, applicationArguments);// 刷新后处理
Duration timeTakenToStartup = Duration.ofNanos(System.nanoTime() - startTime);
if (this.logStartupInfo) {
new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), timeTakenToStartup);
}
listeners.started(context, timeTakenToStartup);// 广播启动完成事件
callRunners(context, applicationArguments);// 执行所有的runner,runner机制,实现对应接口,在SpringBoot启动后能做一些初始化工作,比如Redis预热
}
catch (Throwable ex) {
if (ex instanceof AbandonedRunException) {
throw ex;
}
handleRunFailure(context, ex, listeners);
throw new IllegalStateException(ex);
}
try {
if (context.isRunning()) {
Duration timeTakenToReady = Duration.ofNanos(System.nanoTime() - startTime);
listeners.ready(context, timeTakenToReady);
}
}
catch (Throwable ex) {
if (ex instanceof AbandonedRunException) {
throw ex;
}
handleRunFailure(context, ex, null);
throw new IllegalStateException(ex);
}
return context;
}
我们断点进入context = createApplicationContext();// 断点进入创建Spring容器上下文
protected ConfigurableApplicationContext createApplicationContext() {
return this.applicationContextFactory.create(this.webApplicationType);// DefaultApplicationContextFactory是成员变量就赋值好的默认上下文工厂,webApplicationType类型是SERVLET(根据配置决定的)
}
// 断点进入ServletWebServerApplicationContextFactory的create方法(SpringBoot默认是servlet,所以一般是走这个实现类的create方法)
@Override
public ConfigurableApplicationContext create(WebApplicationType webApplicationType) {
return (webApplicationType != WebApplicationType.SERVLET) ? null : createContext();
}
private ConfigurableApplicationContext createContext() {
if (!AotDetector.useGeneratedArtifacts()) {
// 【核心】构造这个最终Spring容器上下文的时候,创建了初始的beanDefinitionMap中的BeanDefinition
return new AnnotationConfigServletWebServerApplicationContext();// 断点进入
}
return new ServletWebServerApplicationContext();
}
我们断点进入
return new AnnotationConfigServletWebServerApplicationContext();
public AnnotationConfigServletWebServerApplicationContext() {
// 这边注册了5个
this.reader = new AnnotatedBeanDefinitionReader(this);// 断点进入
this.scanner = new ClassPathBeanDefinitionScanner(this);
}
断点进入
this.reader = new AnnotatedBeanDefinitionReader(this);
public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry) {
this(registry, getOrCreateEnvironment(registry));// 点this断点进入
}
// 点this断点进入
public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry, Environment environment) {
Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
Assert.notNull(environment, "Environment must not be null");
this.registry = registry;
this.conditionEvaluator = new ConditionEvaluator(registry, environment, null);// 条件计算器,做条件注解相关的一些工具
// 注册AnnotationConfig的处理器
AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);// 断点进入
}
断点进入
AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
public static void registerAnnotationConfigProcessors(BeanDefinitionRegistry registry) {
registerAnnotationConfigProcessors(registry, null); // 断点进入
}
// 断点进入
// 主要注入了5个bean
public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(
BeanDefinitionRegistry registry, @Nullable Object source) {
DefaultListableBeanFactory beanFactory = unwrapDefaultListableBeanFactory(registry);
if (beanFactory != null) {
if (!(beanFactory.getDependencyComparator() instanceof AnnotationAwareOrderComparator)) {
beanFactory.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE);
}
if (!(beanFactory.getAutowireCandidateResolver() instanceof ContextAnnotationAutowireCandidateResolver)) {
beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());
}
}
Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet<>(8);// BeanDefinition的持有者
// ConfigurationClassPostProcessor的注册
if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);// 转为BeanDefinition
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));
}
if (!registry.containsBeanDefinition(AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
}
// Check for Jakarta Annotations support, and if present add the CommonAnnotationBeanPostProcessor.
if ((jakartaAnnotationsPresent || jsr250Present) &&
!registry.containsBeanDefinition(COMMON_ANNOTATION_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(CommonAnnotationBeanPostProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, COMMON_ANNOTATION_PROCESSOR_BEAN_NAME));
}
// Check for JPA support, and if present add the PersistenceAnnotationBeanPostProcessor.
if (jpaPresent && !registry.containsBeanDefinition(PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition();
try {
def.setBeanClass(ClassUtils.forName(PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME,
AnnotationConfigUtils.class.getClassLoader()));
}
catch (ClassNotFoundException ex) {
throw new IllegalStateException(
"Cannot load optional framework class: " + PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME, ex);
}
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME));
}
if (!registry.containsBeanDefinition(EVENT_LISTENER_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(EventListenerMethodProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_PROCESSOR_BEAN_NAME));
}
if (!registry.containsBeanDefinition(EVENT_LISTENER_FACTORY_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(DefaultEventListenerFactory.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_FACTORY_BEAN_NAME));
}
return beanDefs;
}
ConfigurationClassPostProcessor就是此时进入的容器。