前言
在前文中,我们了解了应用上下文、Bean 工厂以及 Bean 定义的核心组件功能。接下来,我们将深入探讨应用上下文的构造方法。
SpringBoot 版本 2.7.18 中,SpringApplication 的 run 方法执行逻辑包含创建应用程序上下文这一步骤。本文将详细介绍这一环节的实现细节。
// SpringApplication 类方法 public ConfigurableApplicationContext run(String... args) {
// ... 省略部分代码 ...
// 6. 创建应用程序上下文
context = createApplicationContext();
// ... 省略后续步骤 ...
}
源码入口
核心内容在于 new AnnotationConfigServletWebServerApplicationContext() 的调用。
无参构造函数如下:
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);
}
}
该类是应用上下文核心接口的实现类。构造时传入的 this 即 Application 上下文本身,用于构建内部的读取器和扫描器。
一、初始化注解 Bean 定义读取器
AnnotatedBeanDefinitionReader 的构造过程主要涉及三个关键点:获取注册表、获取环境对象、注册注解配置处理器。
public class AnnotatedBeanDefinitionReader {
private final BeanDefinitionRegistry registry;
private ConditionEvaluator conditionEvaluator;
public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry) {
this(registry, getOrCreateEnvironment(registry));
}
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);
// 注册注解配置处理器
AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
}
}
1. BeanDefinitionRegistry(Bean 定义注册接口)
这里的注册表就是当前应用上下文实例。它是 Spring 容器中管理 Bean 定义的核心接口,支持动态注册、移除、查询和别名管理。
public interface BeanDefinitionRegistry extends AliasRegistry {
void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) throws BeanDefinitionStoreException;
void removeBeanDefinition(String beanName) throws NoSuchBeanDefinitionException;
BeanDefinition getBeanDefinition(String beanName) throws NoSuchBeanDefinitionException;
boolean containsBeanDefinition(String beanName);
String[] getBeanDefinitionNames();
int getBeanDefinitionCount();
boolean isBeanNameInUse(String beanName);
}
2. 获取环境对象 Environment
在创建应用上下文之前,环境对象通常已经准备就绪。如果注册表实现了 EnvironmentCapable 接口,则直接获取其中的 Environment;否则创建一个标准的 StandardEnvironment。
private static Environment getOrCreateEnvironment(BeanDefinitionRegistry registry) {
Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
if (registry instanceof EnvironmentCapable) {
return ((EnvironmentCapable) registry).getEnvironment();
}
return new StandardEnvironment();
}
3. 注册注解配置处理器
这是构造过程中的关键一步,用于处理各种注解配置。
public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(BeanDefinitionRegistry registry, @Nullable Object source) {
// 获取默认的 ListableBeanFactory 对象
DefaultListableBeanFactory beanFactory = unwrapDefaultListableBeanFactory(registry);
if (beanFactory != null) {
// 设置依赖比较器,支持 @Order 注解
if (!(beanFactory.getDependencyComparator() instanceof AnnotationAwareOrderComparator)) {
beanFactory.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE);
}
// 设置自动注入候选者解析器
if (!(beanFactory.getAutowireCandidateResolver() instanceof ContextAnnotationAutowireCandidateResolver)) {
beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());
}
}
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 = new RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
}
// 注册 CommonAnnotationBeanPostProcessor,处理 @Resource 等注解
if (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));
}
// 注册 EventListenerMethodProcessor,处理 @EventListener 注解
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));
}
return beanDefs;
}
3.1 获取默认 Bean 工厂
通过反射或类型转换从注册表中获取 DefaultListableBeanFactory。这个工厂负责管理和创建应用上下文中的所有 Bean,维护着 beanDefinitionMap 缓存。
3.2 注册后置处理器(注册 Bean 定义)
这里创建的 RootBeanDefinition 主要用于 Spring 内部处理注解配置,角色被设置为 ROLE_INFRASTRUCTURE。
- ConfigurationClassPostProcessor:处理 @Configuration、@Bean、@Import、@ComponentScan 等注解。
- AutowiredAnnotationBeanPostProcessor:处理 @Autowired、@Value 注解。
- CommonAnnotationBeanPostProcessor:处理 @PostConstruct、@PreDestroy、@Resource 注解。
- EventListenerMethodProcessor:处理 @EventListener 注解。
注册完成后,这些定义会被添加到应用上下文的缓存中。
二、初始化类路径 Bean 定义扫描器
1. 注册默认注解过滤器
ClassPathBeanDefinitionScanner 的构造方法会注册默认的注解扫描过滤器,确保能识别特定注解。
protected void registerDefaultFilters() {
// 添加 @Component 注解的过滤器
this.includeFilters.add(new AnnotationTypeFilter(Component.class));
try {
// 尝试加载 JSR-250 ManagedBean 注解
this.includeFilters.add(new AnnotationTypeFilter(ClassUtils.forName("javax.annotation.ManagedBean", getClassLoader()), false));
} catch (ClassNotFoundException ex) {
// 忽略不支持的情况
}
try {
// 尝试加载 JSR-330 Named 注解
this.includeFilters.add(new AnnotationTypeFilter(ClassUtils.forName("javax.inject.Named", getClassLoader()), false));
} catch (ClassNotFoundException ex) {
// 忽略不支持的情况
}
}
2. 自定义包扫描
此方法将在后续通过传入包路径调用,返回注册的 Bean 定义集合。
protected Set<BeanDefinitionHolder> doScan(String... basePackages) {
Assert.notEmpty(basePackages, "At least one base package must be specified");
Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<>();
for (String basePackage : basePackages) {
Set<BeanDefinition> candidates = findCandidateComponents(basePackage);
for (BeanDefinition candidate : candidates) {
ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);
candidate.setScope(scopeMetadata.getScopeName());
String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);
if (candidate instanceof AbstractBeanDefinition) {
postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName);
}
if (candidate instanceof AnnotatedBeanDefinition) {
AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);
}
if (checkCandidate(beanName, candidate)) {
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
beanDefinitions.add(definitionHolder);
registerBeanDefinition(definitionHolder, this.registry);
}
}
}
return beanDefinitions;
}
总结
本文详细介绍了 SpringBoot 应用上下文 AnnotationConfigServletWebServerApplicationContext 的构造方法。核心在于初始化两个重要组件:一是注解 Bean 定义读取器,负责创建特殊 Bean 定义(如后置处理器)以处理各类注解配置;二是类路径 Bean 定义扫描器,负责扫描指定路径下的组件并将其转换为 Bean 定义注册到容器中。这两个组件共同奠定了 Spring 容器启动的基础。


