一、启动入口
1、代码位置:org.springframework.boot.SpringApplication#run
public ConfigurableApplicationContext run(String... args) {
Startup startup = SpringApplication.Startup.create();
if (this.properties.isRegisterShutdownHook()) {
shutdownHook.enableShutdownHookAddition();
}
DefaultBootstrapContext bootstrapContext = this.createBootstrapContext();
ConfigurableApplicationContext context = null;
this.configureHeadlessProperty();
SpringApplicationRunListeners listeners = this.getRunListeners(args);
listeners.starting(bootstrapContext, this.mainApplicationClass);
try {
ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
ConfigurableEnvironment environment = this.prepareEnvironment(listeners, bootstrapContext, applicationArguments);
Banner printedBanner = this.printBanner(environment);
context = this.createApplicationContext();
context.setApplicationStartup(this.applicationStartup);
// 准备上下文
this.prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner);
// 刷新上下文
this.refreshContext(context);
this.afterRefresh(context, applicationArguments);
startup.started();
if (this.properties.isLogStartupInfo()) {
(new StartupInfoLogger(this.mainApplicationClass, environment)).logStarted(this.getApplicationLog(), startup);
}
listeners.started(context, startup.timeTakenToStarted());
this.callRunners(context, applicationArguments);
} catch (Throwable ex) {
throw this.handleRunFailure(context, ex, listeners);
}
try {
if (context.isRunning()) {
listeners.ready(context, startup.ready());
}
return context;
} catch (Throwable ex) {
throw this.handleRunFailure(context, ex, (SpringApplicationRunListeners)null);
}
}
refresh() - 上下文刷新核心方法(
org.springframework.context.support.AbstractApplicationContext.refresh()
)
2、配置类处理
配置类处理器
核心解析:ConfigurationClassPostProcessor#
postProcessBeanDefinitionRegistry
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
int registryId = System.identityHashCode(registry);
if (this.registriesPostProcessed.contains(registryId)) {
throw new IllegalStateException(
"postProcessBeanDefinitionRegistry already called on this post-processor against " + registry);
}
if (this.factoriesPostProcessed.contains(registryId)) {
throw new IllegalStateException(
"postProcessBeanFactory already called on this post-processor against " + registry);
}
this.registriesPostProcessed.add(registryId);
// 解析配置类
processConfigBeanDefinitions(registry);
}
3、@EnableAutoConfiguration 处理
自动配置选择器
代码位置:AutoConfigurationImportSelector
// 1.选择需要导入的配置类
@Override
public String[] selectImports(AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotationMetadata)) {
return NO_IMPORTS;
}
AutoConfigurationEntry autoConfigurationEntry = getAutoConfigurationEntry(annotationMetadata);
return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
}
protected AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotationMetadata)) {
return EMPTY_ENTRY;
}
AnnotationAttributes attributes = getAttributes(annotationMetadata);
// 2. 加载候选配置
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);
// 3、发送导入事件
fireAutoConfigurationImportEvents(configurations, exclusions);
return new AutoConfigurationEntry(configurations, exclusions);
}
4. 加载自动配置类
配置文件位置:
META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
(Spring Boot 3.x 新位置,替代旧版 spring.factories)
部分内容如下:
org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration
org.springframework.boot.autoconfigure.aop.AopAutoConfiguration
org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration
org.springframework.boot.autoconfigure.batch.BatchAutoConfiguration
org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration
org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration
org.springframework.boot.autoconfigure.context.ConfigurationPropertiesAutoConfiguration
org.springframework.boot.autoconfigure.context.LifecycleAutoConfiguration
org.springframework.boot.autoconfigure.context.MessageSourceAutoConfiguration
org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration
org.springframework.boot.autoconfigure.couchbase.CouchbaseAutoConfiguration
加载逻辑:
org.springframework.boot.autoconfigure.
ImportAutoConfigurationImportSelector#
loadFactoryNames
protected Collection<String> loadFactoryNames(Class<?> source) {
return ImportCandidates.load(source, getBeanClassLoader()).getCandidates();
}
public static ImportCandidates load(Class<?> annotation, ClassLoader classLoader) {
Assert.notNull(annotation, "'annotation' must not be null");
ClassLoader classLoaderToUse = decideClassloader(classLoader);
// 自动导入目录下文件
String location = String.format("META-INF/spring/%s.imports", annotation.getName());
Enumeration<URL> urls = findUrlsInClasspath(classLoaderToUse, location);
List<String> importCandidates = new ArrayList();
while(urls.hasMoreElements()) {
URL url = (URL)urls.nextElement();
importCandidates.addAll(readCandidateConfigurations(url));
}
return new ImportCandidates(importCandidates);
}
5. 条件过滤机智
条件过滤器
核心注解:
-
@ConditionalOnClass
:类路径存在指定类时生效 -
@ConditionalOnMissingBean
:容器中不存在指定Bean时生效 -
@ConditionalOnProperty
:配置属性满足条件时生效
如RedisAutoConfiguration
@AutoConfiguration
@ConditionalOnClass(RedisOperations.class)
@EnableConfigurationProperties(RedisProperties.class)
@Import({ LettuceConnectionConfiguration.class, JedisConnectionConfiguration.class })
public class RedisAutoConfiguration {
@Bean
@ConditionalOnMissingBean(RedisConnectionDetails.class)
PropertiesRedisConnectionDetails redisConnectionDetails(RedisProperties properties,
ObjectProvider<SslBundles> sslBundles) {
return new PropertiesRedisConnectionDetails(properties, sslBundles.getIfAvailable());
}
@Bean
@ConditionalOnMissingBean(name = "redisTemplate")
@ConditionalOnSingleCandidate(RedisConnectionFactory.class)
public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
RedisTemplate<Object, Object> template = new RedisTemplate<>();
template.setConnectionFactory(redisConnectionFactory);
return template;
}
@Bean
@ConditionalOnMissingBean
@ConditionalOnSingleCandidate(RedisConnectionFactory.class)
public StringRedisTemplate stringRedisTemplate(RedisConnectionFactory redisConnectionFactory) {
return new StringRedisTemplate(redisConnectionFactory);
}
}
过滤过程:
org.springframework.boot.autoconfigure.condition.OnClassCondition#
getOutcomes
6. Bean 实例化
DefaultListableBeanFactory#preInstantiateSingletons
处理流程:
-
自动配置类被解析为
ConfigurationClass
-
通过
ConfigurationClassBeanDefinitionReader
注册Bean定义 -
在
finishBeanFactoryInitialization
阶段实例化单例Bean
代码位置:
org.springframework.context.support.AbstractApplicationContext#refresh (9大步骤)
汇总:
1. 启动入口: SpringApplication.run()
│
2. 创建上下文: createApplicationContext()
│
3. 刷新上下文: AbstractApplicationContext.refresh()
│
4. 准备BeanFactory((DefaultListableBeanFactory)调用BeanFactoryPostProcessors
│
5. ConfigurationClassPostProcessor处理配置类
│
6. 解析@SpringBootApplication → 处理@EnableAutoConfiguration
│
7. AutoConfigurationImportSelector加载候选配置
│
8. 从META-INF/spring/*.imports加载配置类
│
9. 条件过滤: @ConditionalOnClass等条件注解评估
│
10. 注册有效的自动配置类
│
11. 实例化自动配置类中的Bean
│
12. 完成应用启动
二、图接
1、核心流程图
2、springboot 启动调用图解
注意事项:
Spring Boot 3.x 使用
AutoConfiguration.imports
替代旧版spring.factories
使用aot.factories 加速AOT 编译时间要求.
自动配置类需满足
@AutoConfiguration
注解条件注解在 Bean 注册阶段 动态生效