前言
在前文中,我们了解了应用上下文、Bean 工厂以及 Bean 定义的核心组件功能,接下来,我们将深入探讨应用上下文的构造方法。
SpringBoot 版本 2.7.18 SpringApplication 的 run 方法的执行逻辑如下,本文将详细介绍第 6 小节:创建应用程序上下文
// SpringApplication 类方法 public ConfigurableApplicationContext run(String... args) {
// 记录应用启动的开始时间
long startTime = System.nanoTime();
// 1. 创建引导上下文,用于管理应用启动时的依赖和资源
DefaultBootstrapContext bootstrapContext = createBootstrapContext();
ConfigurableApplicationContext context = null;
// 配置无头模式属性,以支持在无图形环境下运行
configureHeadlessProperty();
// 2. 获取 Spring 应用启动监听器,用于在应用启动的各个阶段执行自定义逻辑
SpringApplicationRunListeners listeners = getRunListeners(args);
// 启动开始方法(发布开始事件、通知应用监听器 ApplicationListener)
listeners.starting(bootstrapContext, this.mainApplicationClass);
try {
// 3. 解析应用参数
ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
// 4. 准备应用环境,包括读取配置文件和设置环境变量
ConfigurableEnvironment environment = prepareEnvironment(listeners, bootstrapContext, applicationArguments);
// 配置是否忽略 BeanInfo,以加快启动速度
configureIgnoreBeanInfo(environment);
// 5. 打印启动 Banner
Banner printedBanner = printBanner(environment);
// 6. 创建应用程序上下文
context = createApplicationContext();
// 设置应用启动的上下文,用于监控和管理启动过程
context.setApplicationStartup(this.applicationStartup);
// 7. 准备应用上下文,包括加载配置、添加 Bean 等
prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner);
// 8. 刷新上下文,完成 Bean 的加载和依赖注入
refreshContext(context);
// 9. 刷新后的一些操作,如事件发布等
afterRefresh(context, applicationArguments);
// 计算启动应用程序的时间,并记录日志
Duration timeTakenToStartup = Duration.ofNanos(System.nanoTime() - startTime);
if (this.logStartupInfo) {
new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), timeTakenToStartup);
}
// 10. 通知监听器应用启动完成
listeners.started(context, timeTakenToStartup);
// 11. 调用应用程序中的 CommandLineRunner 或 ApplicationRunner,以便执行自定义的启动逻辑
callRunners(context, applicationArguments);
} catch (Throwable ex) {
// 12. 处理启动过程中发生的异常,并通知监听器
handleRunFailure(context, ex, listeners);
throw new IllegalStateException(ex);
}
try {
// 13. 计算应用启动完成至准备就绪的时间,并通知监听器
Duration timeTakenToReady = Duration.ofNanos(System.nanoTime() - startTime);
listeners.ready(context, timeTakenToReady);
} catch (Throwable ex) {
// 处理准备就绪过程中发生的异常
handleRunFailure(context, ex, null);
throw new IllegalStateException(ex);
}
// 返回已启动并准备就绪的应用上下文
return context;
}
源码入口
- 这里核心内容就是
new AnnotationConfigServletWebServerApplicationContext()
// 6. 创建应用程序上下文 context = createApplicationContext();
- 无参构造
public class AnnotationConfigServletWebServerApplicationContext extends ServletWebServerApplicationContext implements AnnotationConfigRegistry {
// 用于读取注解的 Bean 定义读取器
private final AnnotatedBeanDefinitionReader reader;
// 用于扫描类路径并注册 Bean 定义的扫描器
private final ClassPathBeanDefinitionScanner scanner;
// 无参构造函数
public AnnotationConfigServletWebServerApplicationContext() {
// 初始化注解 Bean 定义读取器
this.reader = new AnnotatedBeanDefinitionReader(this);
// 初始化类路径 Bean 定义扫描器
this.scanner = new ClassPathBeanDefinitionScanner(this);
}
}
AnnotationConfigServletWebServerApplicationContext 类图显示,它是应用上下文核心接口的实现类。注解 Bean 定义读取器和类路径 Bean 定义扫描器构造传入的 this 即 Application。
一、初始化注解 Bean 定义读取器
public class AnnotatedBeanDefinitionReader {
// Bean 定义注册表,用于管理和注册 Bean 定义
private final BeanDefinitionRegistry registry;
// 条件评估器,用于判断是否满足某些条件
private ConditionEvaluator conditionEvaluator;
// 构造方法,接收 BeanDefinitionRegistry 作为参数
public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry) {
// 调用带有 Environment 参数的构造方法,环境对象通过注册表自动创建
this(registry, getOrCreateEnvironment(registry));
}
// 构造方法,接收 BeanDefinitionRegistry 和 Environment 作为参数
public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry, Environment environment) {
// 校验参数,确保注册表和环境不为空
Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
Assert.notNull(environment, "Environment must not be null");
// 初始化 Bean 定义注册表
this.registry = registry;
// 初始化条件评估器
this.conditionEvaluator = new ConditionEvaluator(registry, environment, null);
// 注册注解配置处理器,用于处理注解配置
AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
}
}
1、BeanDefinitionRegistry(Bean 定义注册接口)
这里的 Bean 定义注册表 BeanDefinitionRegistry 就是 AnnotatedBeanDefinitionReader 构造传入的 AnnotationConfigServletWebServerApplicationContext。
BeanDefinitionRegistry 是 Spring 容器中用于管理 Bean 定义的核心接口,支持动态注册、移除、查询和别名管理,常用于扩展和动态操作容器内的 Bean 定义。
// 此接口是 Bean 定义注册的核心,用于动态管理 Bean 定义(注册、移除、查询等)
public interface BeanDefinitionRegistry extends AliasRegistry {
// 向注册表中注册一个新的 BeanDefinition
void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) throws BeanDefinitionStoreException;
// 移除给定名称的 BeanDefinition
void removeBeanDefinition(String beanName) throws NoSuchBeanDefinitionException;
// 返回给定名称的 BeanDefinition
BeanDefinition getBeanDefinition(String beanName) throws NoSuchBeanDefinitionException;
// 检查此注册表是否包含具有给定名称的 BeanDefinition
boolean containsBeanDefinition(String beanName);
// 返回此注册表中定义的所有 Bean 的名称
String[] getBeanDefinitionNames();
// 返回注册表中定义的 Bean 的数量
int getBeanDefinitionCount();
// 确定给定的 Bean 名称是否已经在此注册表中使用
boolean isBeanNameInUse(String beanName);
}
/**
* 管理别名的通用接口(提供了注册、删除、查询别名的方法)
*/
public interface AliasRegistry {
// 为给定的名称注册一个别名
void registerAlias(String name, String alias);
// 从注册表中删除指定的别名
void removeAlias(String alias);
// 确定给定的名称是否被定义为别名
;
String[] getAliases(String name);
}
2、获取环境对象 Environment
// AnnotatedBeanDefinitionReader 类方法
private static Environment getOrCreateEnvironment(BeanDefinitionRegistry registry) {
// 校验注册表对象不为空
Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
// 如果注册表实现了 EnvironmentCapable 接口,则直接获取其中的 Environment
if (registry instanceof EnvironmentCapable) {
return ((EnvironmentCapable) registry).getEnvironment();
}
// 如果注册表不具备 Environment,则创建并返回一个标准的 Environment 对象
return new StandardEnvironment();
}
在创建应用上下文之前,有详细介绍应用环境 Environment 的初始化。
3、注册注解配置处理器
public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(BeanDefinitionRegistry registry, @Nullable Object source) {
// 获取默认的 ListableBeanFactory 对象
DefaultListableBeanFactory beanFactory = unwrapDefaultListableBeanFactory(registry);
if (beanFactory != null) {
// AnnotationAwareOrderComparator:这是一个带有注解感知的比较器,用来排序 Bean 的依赖
if (!(beanFactory.getDependencyComparator() instanceof AnnotationAwareOrderComparator)) {
beanFactory.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE);
}
// ContextAnnotationAutowireCandidateResolver:这个解析器是用于处理基于注解的自动注入
if (!(beanFactory.getAutowireCandidateResolver() instanceof ContextAnnotationAutowireCandidateResolver)) {
beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());
}
}
// 创建一个 LinkedHashSet 用于存储 BeanDefinitionHolder
Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet<>(8);
// 注册 ConfigurationClassPostProcessor,用于处理 @Configuration 注解
if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));
}
// 注册 AutowiredAnnotationBeanPostProcessor,用于处理 @Autowired 注解
if (!registry.containsBeanDefinition(AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def (AutowiredAnnotationBeanPostProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
}
(jsr250Present && !registry.containsBeanDefinition(COMMON_ANNOTATION_PROCESSOR_BEAN_NAME)) {
(CommonAnnotationBeanPostProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, COMMON_ANNOTATION_PROCESSOR_BEAN_NAME));
}
(jpaPresent && !registry.containsBeanDefinition(PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME)) {
();
{
def.setBeanClass(ClassUtils.forName(PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME, AnnotationConfigUtils.class.getClassLoader()));
} (ClassNotFoundException ex) {
( + PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME, ex);
}
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME));
}
(!registry.containsBeanDefinition(EVENT_LISTENER_PROCESSOR_BEAN_NAME)) {
(EventListenerMethodProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_PROCESSOR_BEAN_NAME));
}
(!registry.containsBeanDefinition(EVENT_LISTENER_FACTORY_BEAN_NAME)) {
(DefaultEventListenerFactory.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_FACTORY_BEAN_NAME));
}
beanDefs;
}
3.1、获取默认 Bean 工厂
这里的 registry 就是注解应用上下文 AnnotationConfigServletWebServerApplicationContext。
// AnnotationConfigUtils 类方法
@Nullable
private static DefaultListableBeanFactory unwrapDefaultListableBeanFactory(BeanDefinitionRegistry registry) {
if (registry instanceof DefaultListableBeanFactory) {
return (DefaultListableBeanFactory) registry;
} else if (registry instanceof GenericApplicationContext) {
return ((GenericApplicationContext) registry).getDefaultListableBeanFactory();
} else {
return null;
}
}
DefaultListableBeanFactory 是 Spring 框架中的一个核心类,负责管理和创建应用上下文中的所有 Bean。
public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable {
// ==================== 核心属性 ====================
// 存储所有注册的 BeanDefinition,键为 beanName,值为对应的 BeanDefinition
private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);
// 记录所有注册的 beanName,保持注册顺序
private volatile List<String> beanDefinitionNames = new ArrayList<>(256);
}
获取到默认 Bean 工厂以后,设置了两个重要属性:
- AnnotationAwareOrderComparator:这是一个带有注解感知的比较器,用来排序 Bean 的依赖。它比标准的比较器多了对 @Order 注解的支持。
- ContextAnnotationAutowireCandidateResolver:这个解析器是用于处理基于注解的自动注入(例如 @Autowired 注解)。
3.2、注册后置处理器(注册 Bean 定义)
上面创建了很多 RootBeanDefinition,这些 Bean 定义只做 Spring 内部使用,用于处理注解配置。
- ConfigurationClassPostProcessor,用于处理 @Configuration、@Bean、@Import、@ComponentScan 等注解
- AutowiredAnnotationBeanPostProcessor,用于处理 @Autowired、@Value 注解
- CommonAnnotationBeanPostProcessor,用于处理 @PostConstruct、@PreDestroy、@Resource 注解
- EventListenerMethodProcessor,用于处理 @EventListener 注解
创建完 RootBeanDefinition 后,还需要将其添加到应用上下文的缓存中。
// AnnotationConfigUtils 类方法
private static BeanDefinitionHolder registerPostProcessor(BeanDefinitionRegistry registry, RootBeanDefinition definition, String beanName) {
definition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
// 注册 Bean 定义
registry.registerBeanDefinition(beanName, definition);
return new BeanDefinitionHolder(definition, beanName);
}
BeanDefinitionRegistry registry 是应用上下文,调用注册 Bean 定义方法 registerBeanDefinition,实际就是调用默认 Bean 工厂的注册 Bean 定义的方法。
二、初始化类路径 Bean 定义扫描器
1、注册默认注解过滤器
通过 ClassPathBeanDefinitionScanner 的构造方法,最终跳转到最后一个构造方法,核心操作是注册默认的注解扫描过滤器。
注册默认的注解过滤器,确保在组件扫描时,能够识别特定的注解。添加 @Component 注解的过滤器,允许扫描带有 @Component 注解的类,@Controller、@Service、@Repository 也会被扫描到。
// ClassPathScanningCandidateComponentProvider 类方法
protected void registerDefaultFilters() {
// 添加 @Component 注解的过滤器,允许扫描带有 @Component 注解的类
this.includeFilters.add(new AnnotationTypeFilter(Component.class));
// @ManagedBean 是 Java EE 的托管 Bean 注解
// 而 @Named 是 CDI(Jakarta EE)的标准化注解
ClassLoader cl = ClassPathScanningCandidateComponentProvider.class.getClassLoader();
try {
// 尝试加载 javax.annotation.ManagedBean 注解类,如果存在,添加为过滤器
this.includeFilters.add(new AnnotationTypeFilter(((Class<? extends Annotation>) ClassUtils.forName("javax.annotation.ManagedBean", cl)), false));
logger.trace("JSR-250 'javax.annotation.ManagedBean' found and supported for component scanning");
} catch (ClassNotFoundException ex) {
// 如果 JSR-250 API 未找到,跳过该注解支持
}
try {
// 尝试加载 javax.inject.Named 注解类,如果存在,添加为过滤器
this.includeFilters.add(new AnnotationTypeFilter(((Class<? extends Annotation>) ClassUtils.forName("javax.inject.Named", cl)), false));
logger.trace("JSR-330 'javax.inject.Named' annotation found and supported for component scanning");
} catch (ClassNotFoundException ex) {
// 如果 JSR-330 API 未找到,跳过该注解支持
}
}
2、自定义包扫描
此方法将在后续通过传入包路径调用,并返回注册的 Bean 定义集合。
protected Set<BeanDefinitionHolder> doScan(String... basePackages) {
// 检查 basePackages 是否为空,如果为空则抛出异常
Assert.notEmpty(basePackages, "At least one base package must be specified");
// 用于存储扫描到的 Bean 定义
Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<>();
// 遍历传入的每个包路径进行扫描
for (String basePackage : basePackages) {
// 查找当前包路径下符合条件的候选组件
Set<BeanDefinition> candidates = findCandidateComponents(basePackage);
// 遍历候选组件
for (BeanDefinition candidate : candidates) {
// 获取该 Bean 定义的作用域元数据,并设置作用域
ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);
candidate.setScope(scopeMetadata.getScopeName());
// 生成 Bean 的名称
String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);
// 如果候选 Bean 是 AbstractBeanDefinition 类型,进行后处理
if (candidate instanceof AbstractBeanDefinition) {
postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName);
}
// 如果候选 Bean 是 AnnotatedBeanDefinition 类型,处理注解配置
if (candidate instanceof AnnotatedBeanDefinition) {
AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);
}
// 如果当前 Bean 名称和定义符合要求,则继续处理
if (checkCandidate(beanName, candidate)) {
// 创建一个 BeanDefinitionHolder 来包装 Bean 定义和 Bean 名称
(candidate, beanName);
definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, .registry);
beanDefinitions.add(definitionHolder);
registerBeanDefinition(definitionHolder, .registry);
}
}
}
beanDefinitions;
}
总结
本文详细介绍了 SpringBoot 应用上下文 AnnotationConfigServletWebServerApplicationContext 的构造方法中初始化两个重要组件:一是注解 Bean 定义读取器,创建一些特殊 Bean 定义(Spring 内部使用,也叫后置处理器),用于处理@Configuration、@Autowired 等注解;二是类路径 Bean 定义扫描器,用于扫描给定路径下的@Component 注解组件,将其转换为 Bean 定义。


