Spring Boot源码分析
启动类注解
@SpringBootApplication
集成注解
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(
excludeFilters = {@Filter(
type = FilterType.CUSTOM,
classes = {TypeExcludeFilter.class}
), @Filter(
type = FilterType.CUSTOM,
classes = {AutoConfigurationExcludeFilter.class}
)}
)
@Inherited
@Inherited修饰的注解,如果作用在某个类上,其子类是可以继承该注解;
@SpringBootConfiguration
@SpringBootConfiguration 标明了配置类是Spring Boot的配置类
@EnableAutoConfiguration
开启自动装配,实例化start目录以外的bean
@AutoConfigurationPackage
指定自动装配的包
/**
*AutoConfigurationPackages.Registrar.class
将被@SpringBootAPplication标记的包,包装成BasePackage,注册到spring容器中
**/
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@Import({AutoConfigurationPackages.Registrar.class})
public @interface AutoConfigurationPackage {
String[] basePackages() default {};
Class<?>[] basePackageClasses() default {};
}
public abstract class AutoConfigurationPackages {
private static final String BEAN = AutoConfigurationPackages.class.getName();
static class Registrar implements ImportBeanDefinitionRegistrar, DeterminableImports {
/**
* 根据 ImportBeanDefinitionRegistrar 的处理,spring将调用 registerBeanDefinitions() 注册内容
*/
@Override
public void registerBeanDefinitions(AnnotationMetadata metadata,
BeanDefinitionRegistry registry) {
//new PackageImports(metadata).getPackageNames()`就是当前启动类所在的包。
register(registry, new PackageImport(metadata).getPackageName());
}
@Override
public Set<Object> determineImports(AnnotationMetadata metadata) {
return Collections.singleton(new PackageImport(metadata));
}
}
/**
* 处理具体的注册操作
* 1. 如果 beanFacotry 中包含 BEAN,则将传入的包名添加到 BEAN 对应的 BeanDefinition 的构造方法参数值上;
* 2. 如果 beanFacotry 中不包含 BEAN,则创建 beanDefinition,设置参数值,然后将其注册到 beanFacotry。
* 注册到beanFacotry中的bean为BasePackages
*/
public static void register(BeanDefinitionRegistry registry, String... packageNames) {
if (registry.containsBeanDefinition(BEAN)) {
BeanDefinition beanDefinition = registry.getBeanDefinition(BEAN);
// bean 是 BasePackages,构造方法是 BasePackages(String... names),这里获取原本的构造参数的值
ConstructorArgumentValues constructorArguments
= beanDefinition.getConstructorArgumentValues();
// 将原本的构造参数值,以及传入的 packageNames 统一添加到构造方法的第0个参数值上
constructorArguments.addIndexedArgumentValue(0,
addBasePackages(constructorArguments, packageNames));
}
else {
GenericBeanDefinition beanDefinition = new GenericBeanDefinition();
// 设置BeanClass为BasePackages.class
beanDefinition.setBeanClass(BasePackages.class);
// 设置构造方法的参数值
beanDefinition.getConstructorArgumentValues().addIndexedArgumentValue(0, packageNames);
beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
registry.registerBeanDefinition(BEAN, beanDefinition);
}
}
/**
* packageName 的包装类
* packageName 是传入类所在的包名,在PackageImport的构造方法中获取
*/
private static final class PackageImport {
private final String packageName;
PackageImport(AnnotationMetadata metadata) {
// 获取传入类所在包名
this.packageName = ClassUtils.getPackageName(metadata.getClassName());
}
String getPackageName() {
return this.packageName;
}
// 省略 equals/toString/hashCode 方法
...
}
/**
* 注解到 beanFactory 中的类
* 该类中有一个List结构,用来保存包扫描路径
*/
static final class BasePackages {
// 包扫描路径在这里保存
private final List<String> packages;
private boolean loggedBasePackageInfo;
BasePackages(String... names) {
List<String> packages = new ArrayList<>();
for (String name : names) {
if (StringUtils.hasText(name)) {
packages.add(name);
}
}
this.packages = packages;
}
}
@Import({AutoConfigurationImportSelector.class})
根据配置文件spring.factories,将bean注入到容器中
AutoConfigurationImportSelector 开启自动配置类的导包的选择器(导入哪些组件的选择器),DeferedImportSelector处理自动配置。如果需要@EnableAutoConfiguration的自定义变量,也可以对该类进行子类化。
public interface DeferredImportSelector extends ImportSelector {
...
interface Group {
/**
* 处理导入操作
*/
void process(AnnotationMetadata metadata, DeferredImportSelector selector);
/**
* 返回导入类
*/
Iterable<Entry> selectImports()
}
}
@ComponentScan()
@ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
@ComponentScan()指定包扫描路径
TypeExcludeFilter: 这个类表示在进行包扫描时,可以排除一些类。AutoConfigurationExcludeFilter:用来排除自动配置类,也就是说,spring 在进行包扫描时,不会扫描自动配置类.
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//
package org.springframework.boot.autoconfigure;
import java.io.IOException;
import java.util.List;
import org.springframework.beans.factory.BeanClassLoaderAware;
import org.springframework.boot.context.annotation.ImportCandidates;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.type.classreading.MetadataReader;
import org.springframework.core.type.classreading.MetadataReaderFactory;
import org.springframework.core.type.filter.TypeFilter;
public class AutoConfigurationExcludeFilter implements TypeFilter, BeanClassLoaderAware {
private ClassLoader beanClassLoader;
private volatile List<String> autoConfigurations;
public AutoConfigurationExcludeFilter() {
}
public void setBeanClassLoader(ClassLoader beanClassLoader) {
this.beanClassLoader = beanClassLoader;
}
public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException {
return this.isConfiguration(metadataReader) && this.isAutoConfiguration(metadataReader);
}
private boolean isConfiguration(MetadataReader metadataReader) {
return metadataReader.getAnnotationMetadata().isAnnotated(Configuration.class.getName());
}
private boolean isAutoConfiguration(MetadataReader metadataReader) {
boolean annotatedWithAutoConfiguration = metadataReader.getAnnotationMetadata().isAnnotated(AutoConfiguration.class.getName());
return annotatedWithAutoConfiguration || this.getAutoConfigurations().contains(metadataReader.getClassMetadata().getClassName());
}
protected List<String> getAutoConfigurations() {
if (this.autoConfigurations == null) {
this.autoConfigurations = ImportCandidates.load(AutoConfiguration.class, this.beanClassLoader).getCandidates();
}
return this.autoConfigurations;
}
}
启动流程
启动器入口
@SpringBootApplication
public class UserApplication {
public static void main(String[] args) {
//run 方法启动入口
SpringApplication.run(UserApplication.class, args);
}
}
public static ConfigurableApplicationContext run(Class<?> primarySource, String... args) {
return run(new Class[]{primarySource}, args);
}
public static ConfigurableApplicationContext run(Class<?>[] primarySources, String[] args) {
//primarySources 就是 class com.user.UserApplication
//args就是参数
return (new SpringApplication(primarySources)).run(args);
}
重要方法
SpringApplicaion(primarySources) 构造方法
run(agrs)
SpringApplicaion(primarySources) 构造方法
public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
//resourceLoader 设置成员变量,这里的值为null
this.resourceLoader = resourceLoader;
Assert.notNull(primarySources, "PrimarySources must not be null");
//设置primarySourse成员变量 UserApplication.class
this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
//当前的web应用类型
this.webApplicationType = WebApplicationType.deduceFromClasspath();
this.bootstrapRegistryInitializers = new ArrayList<>(
getSpringFactoriesInstances(BootstrapRegistryInitializer.class));
//设置初始化器,从META-INF/spring.factories中获取配置
setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
//设值监听器,从META-INF/spring.factories中获取配置
setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
//返回包含main()方法的class
this.mainApplicationClass = deduceMainApplicationClass();
}
WebApplicationType
spring-boot-starter-web 所以是web应用
package org.springframework.boot;
import org.springframework.aot.hint.RuntimeHints;
import org.springframework.aot.hint.RuntimeHintsRegistrar;
import org.springframework.aot.hint.TypeReference;
import org.springframework.util.ClassUtils;
/**
* An enumeration of possible types of web application.
*
* @author Andy Wilkinson
* @author Brian Clozel
* @since 2.0.0
*/
public enum WebApplicationType {
/**
* 不是web应用
* embedded web server.
*/
NONE,
/**
* servlet 类型的 web应用
* embedded servlet web server.
*/
SERVLET,
/**
* reactive 类型的web应用
* embedded reactive web server.
*/
REACTIVE;
private static final String[] SERVLET_INDICATOR_CLASSES = { "jakarta.servlet.Servlet",
"org.springframework.web.context.ConfigurableWebApplicationContext" };
private static final String WEBMVC_INDICATOR_CLASS = "org.springframework.web.servlet.DispatcherServlet";
private static final String WEBFLUX_INDICATOR_CLASS = "org.springframework.web.reactive.DispatcherHandler";
private static final String JERSEY_INDICATOR_CLASS = "org.glassfish.jersey.servlet.ServletContainer";
static WebApplicationType deduceFromClasspath() {
// classpath中仅存在 WEBFLUX 相关类
if (ClassUtils.isPresent(WEBFLUX_INDICATOR_CLASS, null) && !ClassUtils.isPresent(WEBMVC_INDICATOR_CLASS, null)
&& !ClassUtils.isPresent(JERSEY_INDICATOR_CLASS, null)) {
return WebApplicationType.REACTIVE;
}
// classpath 不存在 servlet相关类
for (String className : SERVLET_INDICATOR_CLASSES) {
if (!ClassUtils.isPresent(className, null)) {
return WebApplicationType.NONE;
}
}
//默认 web 类型为servlet 相关类
//同时存在WEBFLUX 与 SERVLET相关类 最终返回的是SERVLET
return WebApplicationType.SERVLET;
}
static class WebApplicationTypeRuntimeHints implements RuntimeHintsRegistrar {
@Override
public void registerHints(RuntimeHints hints, ClassLoader classLoader) {
for (String servletIndicatorClass : SERVLET_INDICATOR_CLASSES) {
registerTypeIfPresent(servletIndicatorClass, classLoader, hints);
}
registerTypeIfPresent(JERSEY_INDICATOR_CLASS, classLoader, hints);
registerTypeIfPresent(WEBFLUX_INDICATOR_CLASS, classLoader, hints);
registerTypeIfPresent(WEBMVC_INDICATOR_CLASS, classLoader, hints);
}
private void registerTypeIfPresent(String typeName, ClassLoader classLoader, RuntimeHints hints) {
if (ClassUtils.isPresent(typeName, classLoader)) {
hints.reflection().registerType(TypeReference.of(typeName));
}
}
}
}
设置初始化器 setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
从META-INF/spring.factories 进行实例化
private <T> List<T> getSpringFactoriesInstances(Class<T> type, ArgumentResolver argumentResolver) {
return SpringFactoriesLoader.forDefaultResourceLocation(getClassLoader()).load(type, argumentResolver);
}
public class SpringFactoriesLoader{
public static SpringFactoriesLoader forDefaultResourceLocation(@Nullable ClassLoader classLoader) {
return forResourceLocation(FACTORIES_RESOURCE_LOCATION, classLoader);
}
public static SpringFactoriesLoader forResourceLocation(String resourceLocation, @Nullable ClassLoader classLoader) {
Assert.hasText(resourceLocation, "'resourceLocation' must not be empty");
ClassLoader resourceClassLoader = (classLoader != null ? classLoader :
SpringFactoriesLoader.class.getClassLoader());
Map<String, SpringFactoriesLoader> loaders = cache.computeIfAbsent(
resourceClassLoader, key -> new ConcurrentReferenceHashMap<>());
return loaders.computeIfAbsent(resourceLocation, key ->
new SpringFactoriesLoader(classLoader, loadFactoriesResource(resourceClassLoader, resourceLocation)));
}
protected static Map<String, List<String>> loadFactoriesResource(ClassLoader classLoader, String resourceLocation) {
Map<String, List<String>> result = new LinkedHashMap<>();
try {
Enumeration<URL> urls = classLoader.getResources(resourceLocation);
while (urls.hasMoreElements()) {
UrlResource resource = new UrlResource(urls.nextElement());
Properties properties = PropertiesLoaderUtils.loadProperties(resource);
properties.forEach((name, value) -> {
String[] factoryImplementationNames = StringUtils.commaDelimitedListToStringArray((String) value);
List<String> implementations = result.computeIfAbsent(((String) name).trim(),
key -> new ArrayList<>(factoryImplementationNames.length));
Arrays.stream(factoryImplementationNames).map(String::trim).forEach(implementations::add);
});
}
result.replaceAll(SpringFactoriesLoader::toDistinctUnmodifiableList);
}
catch (IOException ex) {
throw new IllegalArgumentException("Unable to load factories from location [" + resourceLocation + "]", ex);
}
return Collections.unmodifiableMap(result);
}
}
setInitalizers()
会把项目中所有的spring.factories中的key都存到内存里,后面可以快速找到对应key
/**
* Sets the {@link ApplicationContextInitializer} that will be applied to the Spring
* {@link ApplicationContext}.
* @param initializers the initializers to set
*/
public void setInitializers(Collection<? extends ApplicationContextInitializer<?>> initializers) {
this.initializers = new ArrayList<>(initializers);
}
设置监听器
流程和实例化器一致
获取main()方法
获取调用栈,遍历得到包含main方法的类
this.mainApplicationClass = deduceMainApplicationClass();
private Class<?> deduceMainApplicationClass() {
return StackWalker.getInstance(StackWalker.Option.RETAIN_CLASS_REFERENCE)
.walk(this::findMainClass)
.orElse(null);
}
private Optional<Class<?>> findMainClass(Stream<StackFrame> stack) {
return stack.filter((frame) -> Objects.equals(frame.getMethodName(), "main"))
.findFirst()
.map(StackWalker.StackFrame::getDeclaringClass);
}
run()
public ConfigurableApplicationContext run(String... args) {
//开启钩子,用作在进程结束后做善后工作
if (this.registerShutdownHook) {
SpringApplication.shutdownHook.enableShutdowHookAddition();
}
//测量方法执行时间
long startTime = System.nanoTime();
//启动期间传递上下文信息和执行逻辑
DefaultBootstrapContext bootstrapContext = createBootstrapContext();
//准备空的ApplicationContext,以及一组异常报告器
ConfigurableApplicationContext context = null;
//配置 headless 属性,java.awt.headless,java.awt.headless模式是系统的一种配置模式,在系统可能缺少显示设备、键盘或鼠标这些外设的情况下可以使用该模式
configureHeadlessProperty();
// 获取监听器,也是从 META-INF/spring.factories 中获取
SpringApplicationRunListeners listeners = getRunListeners(args);
// starting():首次启动run方法时立即调用。可用于非常早期的初始化(准备运行时环境之前)。
// 发布事件
listeners.starting(bootstrapContext, this.mainApplicationClass);
try {
// 封装传入的参数,args是启动Spring应用的命令行参数,该参数可以在Spring应用中被访问。如:--server.port=9000
ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
// 处理环境参数
// 创建并配置当前SpringBoot应用将要使用的Environment
ConfigurableEnvironment environment = prepareEnvironment(listeners, bootstrapContext, applicationArguments);
//准备Banner打印器 - 就是启动Spring Boot的时候打印在console上的ASCII艺术字体
Banner printedBanner = printBanner(environment);
//创建applicationContext 核心容器
context = createApplicationContext();
//让核心容器跑起来
context.setApplicationStartup(this.applicationStartup);
//准备上下文,设置了一系列的属性值
//这一步主要是在容器刷新之前的准备动作。包含一个非常关键的操作:将启动类注入容器,为后续开启自动化配置奠定基础。
prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner);
//刷新容器 调用 AbstractApplicationContext.refresh,启动spring容器
refreshContext(context);
//最后刷新
//刷新后的处理
//扩展接口,设计模式中的模板方法,默认为空实现。
// 如果有自定义需求,可以重写该方法。比如打印一些启动结束log,或者一些其它后置处理
afterRefresh(context, applicationArguments);
//停止统计时间
Duration timeTakenToStartup = Duration.ofNanos(System.nanoTime() - startTime);
if (this.logStartupInfo) {
new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), timeTakenToStartup);
}
//发布事件
listeners.started(context, timeTakenToStartup);
调用 runner,实现了 ApplicationRunner或CommandLineRunner 的接口
//用于调用项目中自定义的执行器XxxRunner类,使得在项目启动完成后立即执行一些特定程序
//Runner 运行器用于在服务启动时进行一些业务初始化操作,这些操作只在服务启动后执行一次。
//Spring Boot提供了ApplicationRunner和CommandLineRunner两种服务接口
callRunners(context, applicationArguments);
}
catch (Throwable ex) {
if (ex instanceof AbandonedRunException) {
throw ex;
}
// 如果发生异常,则进行处理,并抛出 IllegalStateException 异常
handleRunFailure(context, ex, listeners);
throw new IllegalStateException(ex);
}
try {
//发布应用上下文就绪事件
//表示在前面一切初始化启动都没有问题的情况下,使用运行监听器SpringApplicationRunListener持续运行配置好的应用上下文ApplicationContext,
// 这样整个Spring Boot项目就正式启动完成了
if (context.isRunning()) {
Duration timeTakenToReady = Duration.ofNanos(System.nanoTime() - startTime);
listeners.ready(context, timeTakenToReady);
}
}
catch (Throwable ex) {
if (ex instanceof AbandonedRunException) {
throw ex;
}
// 如果发生异常,则进行处理,并抛出 IllegalStateException 异常
handleRunFailure(context, ex, null);
throw new IllegalStateException(ex);
}
return context;
}
DefaultBootstrapContext
private DefaultBootstrapContext createBootstrapContext() {
DefaultBootstrapContext bootstrapContext = new DefaultBootstrapContext();//创建 DefaultBootstrapContext实例 ->
this.bootstrapRegistryInitializers.forEach((initializer) -> { //遍历列表 列表内容:bootstraptInitializer 注册表初始器
initializer.initialize(bootstrapContext); //每个注册表初始器初始化引导程序上下文
});
return bootstrapContext;
}
configureHeadlessProperty()
定义了一系列的方法来监听 springboot 的启动过程,方法的说明已经在文档中有详细定义,如果我们需要在 springboot 的启动中的某个过程做一些事情,就可以实现 SpringApplicationRunListener 然后重写对应的方法
listeners.starting()就是遍历所有的监听器,逐一调用其 starting() 罢了,this.listeners 就是上面获取到的所有的运行监听器
java.awt.headless 的值设置到了系统变量,设置成 true,缺少显示设备
监听器
public interface SpringApplicationRunListener {
/**
* 首次启动run方法时立即调用。可用于非常早期的初始化。
*/
default void starting() {
}
/**
* 准备好环境(Environment构建完成),但在创建ApplicationContext之前调用。
*/
default void environmentPrepared(ConfigurableEnvironment environment) {
}
/**
* 在创建和构建ApplicationContext之后,但在加载之前调用。
*/
default void contextPrepared(ConfigurableApplicationContext context) {
}
/**
* ApplicationContext已加载但在刷新之前调用。
*/
default void contextLoaded(ConfigurableApplicationContext context) {
}
/**
* ApplicationContext已刷新,应用程序已启动,
* 但尚未调用CommandLineRunners和ApplicationRunners。
*/
default void started(ConfigurableApplicationContext context) {
}
/**
* 在运行方法彻底完成之前立即调用,
* 刷新ApplicationContext并调用所有CommandLineRunners和ApplicationRunner。
*/
default void running(ConfigurableApplicationContext context) {
}
/**
* 在运行应用程序时失败时调用。
*/
default void failed(ConfigurableApplicationContext context, Throwable exception) {
}
}
准备运行环境ConfigurableEnvironment environment = prepareEnvironment(listeners, bootstrapContext, applicationArguments)
private ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners listeners,
DefaultBootstrapContext bootstrapContext, ApplicationArguments applicationArguments) {
// Create and configure the environment
ConfigurableEnvironment environment = getOrCreateEnvironment();
// 配置运行时环境
configureEnvironment(environment, applicationArguments.getSourceArgs());
ConfigurationPropertySources.attach(environment);
// SpringApplicationRunListener 的 environmentPrepared 方法
// (Environment构建完成,但在创建ApplicationContext之前)
// 配置文件加载监听器(ConfigFileApplicationListener)
listeners.environmentPrepared(bootstrapContext, environment);
DefaultPropertiesPropertySource.moveToEnd(environment);
Assert.state(!environment.containsProperty("spring.main.environment-prefix"),
"Environment prefix cannot be set via properties.");
// 环境与应用绑定
bindToSpringApplication(environment);
if (!this.isCustomEnvironment) {
EnvironmentConverter environmentConverter = new EnvironmentConverter(getClassLoader());
environment = environmentConverter.convertEnvironmentIfNecessary(environment, deduceEnvironmentClass());
}
ConfigurationPropertySources.attach(environment);
return environment;
}
获取或创建环境
private ConfigurableEnvironment getOrCreateEnvironment() {
if (this.environment != null) {
return this.environment;
}
ConfigurableEnvironment environment = this.applicationContextFactory.createEnvironment(this.webApplicationType);
if (environment == null && this.applicationContextFactory != ApplicationContextFactory.DEFAULT) {
environment = ApplicationContextFactory.DEFAULT.createEnvironment(this.webApplicationType);
}
return (environment != null) ? environment : new ApplicationEnvironment();
}
配置获取或创建环境
protected void configureEnvironment(ConfigurableEnvironment environment, String[] args) {
if (this.addConversionService) {
// 添加转换器,处理参数类型转换,如 String转Number,Integer转Enum等
ConversionService conversionService = ApplicationConversionService.getSharedInstance();
environment.setConversionService((ConfigurableConversionService) conversionService);
}
// 将启动参数添加到 environment 中 形如 java -jar xxx.jar --a1=aaa --b1=bbb
configurePropertySources(environment, args);
// 处理 ActiveProfiles 值
configureProfiles(environment, args);
}
createApplicationContext()创建核心容器 IOC
private <T> T getFromSpringFactories(WebApplicationType webApplicationType,
BiFunction<ApplicationContextFactory, WebApplicationType, T> action, Supplier<T> defaultResult) {
for (ApplicationContextFactory candidate : SpringFactoriesLoader.loadFactories(ApplicationContextFactory.class,
getClass().getClassLoader())) {
T result = action.apply(candidate, webApplicationType);
if (result != null) {
return result;
}
}
return (defaultResult != null) ? defaultResult.get() : null;
}
public class GenericApplicationContext extends AbstractApplicationContext implements BeanDefinitionRegistry {
private final DefaultListableBeanFactory beanFactory;
@Nullable
private ResourceLoader resourceLoader;
private boolean customClassLoader;
private final AtomicBoolean refreshed;
public GenericApplicationContext() {
this.customClassLoader = false;
this.refreshed = new AtomicBoolean();
this.beanFactory = new DefaultListableBeanFactory();
}
public GenericApplicationContext(DefaultListableBeanFactory beanFactory) {
this.customClassLoader = false;
this.refreshed = new AtomicBoolean();
Assert.notNull(beanFactory, "BeanFactory must not be null");
this.beanFactory = beanFactory;
}
}
容器准备 prepareContext()
private void prepareContext(DefaultBootstrapContext bootstrapContext, ConfigurableApplicationContext context,
ConfigurableEnvironment environment, SpringApplicationRunListeners listeners,
ApplicationArguments applicationArguments, Banner printedBanner) {
// 将创建好的应用环境设置到IOC容器中
context.setEnvironment(environment);
// 设置容器的一些参数
postProcessApplicationContext(context);
addAotGeneratedInitializerIfNecessary(this.initializers);
applyInitializers(context);
// 监听器:SpringApplicationRunListeners的contextPrepared方法
// (在创建和准备ApplicationContext之后,但在加载之前)
listeners.contextPrepared(context);
bootstrapContext.close(context);
// 打印个日志
if (this.logStartupInfo) {
logStartupInfo(context.getParent() == null);
logStartupProfileInfo(context);
}
// 获取beanFactory
ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
// 将运行参数作为bean注册到beanFactory中
beanFactory.registerSingleton("springApplicationArguments", applicationArguments);
// 将 banner 作为bean注册到beanFactory中
if (printedBanner != null) {
beanFactory.registerSingleton("springBootBanner", printedBanner);
}
// 是否允许bean的信息被覆盖
if (beanFactory instanceof AbstractAutowireCapableBeanFactory autowireCapableBeanFactory) {
autowireCapableBeanFactory.setAllowCircularReferences(this.allowCircularReferences);
if (beanFactory instanceof DefaultListableBeanFactory listableBeanFactory) {
listableBeanFactory.setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
}
}
// 处理懒加载
if (this.lazyInitialization) {
context.addBeanFactoryPostProcessor(new LazyInitializationBeanFactoryPostProcessor());
}
context.addBeanFactoryPostProcessor(new PropertySourceOrderingBeanFactoryPostProcessor(context));
if (!AotDetector.useGeneratedArtifacts()) {
// 获取所有资源
Set<Object> sources = getAllSources();
Assert.notEmpty(sources, "Sources must not be empty");
// 加载 class
load(context, sources.toArray(new Object[0]));
}
// 发布事件
listeners.contextLoaded(context);
}
private void addAotGeneratedInitializerIfNecessary(List<ApplicationContextInitializer<?>> initializers) {
if (AotDetector.useGeneratedArtifacts()) {
List<ApplicationContextInitializer<?>> aotInitializers = new ArrayList<>(
initializers.stream().filter(AotApplicationContextInitializer.class::isInstance).toList());
if (aotInitializers.isEmpty()) {
String initializerClassName = this.mainApplicationClass.getName() + "__ApplicationContextInitializer";
aotInitializers.add(AotApplicationContextInitializer.forInitializerClasses(initializerClassName));
}
initializers.removeAll(aotInitializers);
initializers.addAll(0, aotInitializers);
}
}
刷新容器 refresh()
private void refreshContext(ConfigurableApplicationContext context) {
// 启动spring容器
refresh(context);
if (this.registerShutdownHook) {
try {
// 注册 ShutdownHook
context.registerShutdownHook();
}
catch (AccessControlException ex) {
// Not allowed in some environments.
}
}
}
public void refresh() throws BeansException, IllegalStateException {
synchronized(this.startupShutdownMonitor) {
StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");
//准备此上下文以进行刷新。将 servletContext 与 servletConfig 设置到了 Environment 中。
this.prepareRefresh();
//告诉子类刷新内部 Bean 工厂
ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();
// 准备 Bean 工厂以在此上下文中使用。
this.prepareBeanFactory(beanFactory);
try {
// 允许在上下文子类中对 Bean 工厂进行后处理。这个 BeanPostProcessor 是用来处理 ServletContextAware 与 ServletConfigAware 两个 Aware 接口的
this.postProcessBeanFactory(beanFactory);
StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");
// 执行 BeanFactoryPostProcessors。在这个方法中,有个重的 BeanFactoryPostProcessor 会被执行:ConfigurationClassPostProcessor,springboot 的自动装配的启用注解 @EnableAutoConfiguration 会在这里处理,自动装配类的加载、条件注解也是在 ConfigurationClassPostProcessor 中
this.invokeBeanFactoryPostProcessors(beanFactory);
// 注册 BeanPostProcessor
this.registerBeanPostProcessors(beanFactory);
beanPostProcess.end();
// 初始化此上下文的消息源,用于国际化操作。
this.initMessageSource();
// 为此上下文初始化事件多播程序。
this.initApplicationEventMulticaster();
// 在特定上下文子类中初始化其他特殊 bean。web 服务器是在这个方法中创建的,如tomcat/jetty等
this.onRefresh();
// 注册事件监听器
this.registerListeners();
// 初始化单例
beanthis.finishBeanFactoryInitialization(beanFactory);
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 {
// 重置 Spring 核心中的常见内省缓存,因为我们可能不再需要单例 Bean 的元数据了
this.resetCommonCaches();
contextRefresh.end();
}
}
}
刷新后处理afterRefresh()
一个空方法,springboot 提供的扩展
callRunners()
springboot 为我们提供了两个接口:ApplicationRunner 与
CommandLineRunner,我们可以实现它来完成一些操作
private void callRunners(ApplicationContext context, ApplicationArguments args) {
List<Object> runners = new ArrayList<>();
// 获取所有的 ApplicationRunner 与 CommandLineRunner
runners.addAll(context.getBeansOfType(ApplicationRunner.class).values());
runners.addAll(context.getBeansOfType(CommandLineRunner.class).values());
// 排序
AnnotationAwareOrderComparator.sort(runners);
// 遍历调用
for (Object runner : new LinkedHashSet<>(runners)) {
// 调用 ApplicationRunner#run 方法
if (runner instanceof ApplicationRunner) {
callRunner((ApplicationRunner) runner, args);
}
// 调用 CommandLineRunner#run 方法
if (runner instanceof CommandLineRunner) {
callRunner((CommandLineRunner) runner, args);
}
}
}
/**
* 调用 ApplicationRunner#run 方法
*/
private void callRunner(ApplicationRunner runner, ApplicationArguments args) {
try {
(runner).run(args);
}
catch (Exception ex) {
throw new IllegalStateException("Failed to execute ApplicationRunner", ex);
}
}
/**
* 调用 CommandLineRunner#run 方法
*/
private void callRunner(CommandLineRunner runner, ApplicationArguments args) {
try {
(runner).run(args.getSourceArgs());
}
catch (Exception ex) {
throw new IllegalStateException("Failed to execute CommandLineRunner", ex);
}
}
总结
目前Spring Boot 3.×源码分析作者也只是浅浅的理解了一部分,欢迎大家一起讨论,后续会一直更新该博客,将自己最新的理解补充进来。
参考链接https://blog.youkuaiyun.com/Ares___/article/details/128087439,内容很棒,同学们想更深入的了解可跳转此链接,为该博主打call!!!