跳到主要内容SpringBoot 源码解析:AnnotationConfigServletWebServerApplicationContext 构造方法 | 极客日志Javajava
SpringBoot 源码解析:AnnotationConfigServletWebServerApplicationContext 构造方法
综述由AI生成SpringBoot 应用上下文 AnnotationConfigServletWebServerApplicationContext 构造方法主要完成两个核心组件的初始化:注解 Bean 定义读取器和类路径 Bean 定义扫描器。读取器负责处理 @Configuration 等注解并注册内部后置处理器,扫描器负责扫描指定包路径下的@Component 组件。此过程确立了 Spring 容器的基础 Bean 定义管理机制,为后续 Bean 加载和依赖注入奠定基础。
落日余晖15 浏览 前言
在前文中,我们了解了应用上下文、Bean 工厂以及 Bean 定义的核心组件功能,接下来,我们将深入探讨应用上下文的构造方法。
SpringBoot 版本 2.7.18 SpringApplication 的 run 方法的执行逻辑如下,本文将详细介绍第 6 小节:创建应用程序上下文
public ConfigurableApplicationContext run(String... args) {
long startTime = System.nanoTime();
DefaultBootstrapContext bootstrapContext = createBootstrapContext();
ConfigurableApplicationContext context = null;
configureHeadlessProperty();
SpringApplicationRunListeners listeners = getRunListeners(args);
listeners.starting(bootstrapContext, this.mainApplicationClass);
try {
ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
ConfigurableEnvironment environment = prepareEnvironment(listeners, bootstrapContext, applicationArguments);
configureIgnoreBeanInfo(environment);
printBanner(environment);
context = createApplicationContext();
context.setApplicationStartup(.applicationStartup);
prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner);
refreshContext(context);
afterRefresh(context, applicationArguments);
Duration.ofNanos(System.nanoTime() - startTime);
(.logStartupInfo) {
(.mainApplicationClass).logStarted(getApplicationLog(), timeTakenToStartup);
}
listeners.started(context, timeTakenToStartup);
callRunners(context, applicationArguments);
} (Throwable ex) {
handleRunFailure(context, ex, listeners);
(ex);
}
{
Duration.ofNanos(System.nanoTime() - startTime);
listeners.ready(context, timeTakenToReady);
} (Throwable ex) {
handleRunFailure(context, ex, );
(ex);
}
context;
}
Banner
printedBanner
=
this
Duration
timeTakenToStartup
=
if
this
new
StartupInfoLogger
this
catch
throw
new
IllegalStateException
try
Duration
timeTakenToReady
=
catch
null
throw
new
IllegalStateException
return
源码入口
- 这里核心内容就是
new AnnotationConfigServletWebServerApplicationContext()
context = createApplicationContext();
public class AnnotationConfigServletWebServerApplicationContext extends ServletWebServerApplicationContext implements AnnotationConfigRegistry {
private final AnnotatedBeanDefinitionReader reader;
private final ClassPathBeanDefinitionScanner scanner;
public AnnotationConfigServletWebServerApplicationContext() {
this.reader = new AnnotatedBeanDefinitionReader(this);
this.scanner = new ClassPathBeanDefinitionScanner(this);
}
}
AnnotationConfigServletWebServerApplicationContext 类图如下,其实就是应用上下文核心接口 Application 的实现类,那么注解 Bean 定义读取器和类路径 Bean 定义扫描器构造传入的 this 即 Application。
一、初始化注解 Bean 定义读取器
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 定义注册接口)
这里的 Bean 定义注册表 BeanDefinitionRegistry 就是 AnnotatedBeanDefinitionReader 构造传入的 AnnotationConfigServletWebServerApplicationContext。
BeanDefinitionRegistry 是 Spring 容器中用于管理 Bean 定义的核心接口,支持动态注册、移除、查询和别名管理,常用于扩展和动态操作容器内的 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);
}
public interface AliasRegistry {
void registerAlias(String name, String alias);
void removeAlias(String alias);
boolean isAlias(String name);
String[] getAliases(String name);
}
2、获取环境对象 Environment
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();
}
在创建应用上下文之前,有详细介绍应用环境 Environment 的初始化。
3、注册注解配置处理器

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);
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));
}
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));
}
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));
}
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;
}
3.1、获取默认 Bean 工厂
这里的 registry 就是注解应用上下文 AnnotationConfigServletWebServerApplicationContext,从上面的类图可知 GenericApplicationContext 是父类之一。
@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,提供了 Bean 定义的注册、查找和生命周期管理功能。
public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable {
private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);
private volatile List<String> beanDefinitionNames = new ArrayList<>(256);
}
获取到默认 Bean 工厂以后,设置了两个重要属性
AnnotationAwareOrderComparator:这是一个带有注解感知的比较器,用来排序 Bean 的依赖。它比标准的比较器多了对 @Order 注解的支持,可以确保按照注解指定的优先级排序依赖关系。
ContextAnnotationAutowireCandidateResolver:这个解析器是用于处理基于注解的自动注入(例如@Autowired 注解)。它负责在自动注入过程中,决定哪些 Bean 可以作为自动注入的候选者。
3.2、注册后置处理器(注册 Bean 定义)
上面创建了很多 RootBeanDefinition,这些 Bean 定义只做 Spring 内部使用,用于处理注解配置
- ConfigurationClassPostProcessor,用于处理 @Configuration、@Bean、@Import、@ComponentScan 等注解
- AutowiredAnnotationBeanPostProcessor,用于处理 @Autowired、@Value 注解
- CommonAnnotationBeanPostProcessor,用于处理 @PostConstruct、@PreDestroy、@Resource 注解
- EventListenerMethodProcessor,用于处理 @EventListener 注解
创建完 RootBeanDefinition 后,还需要将其添加到应用上下文的缓存中
Bean 定义的角色设置为 2,表示框架内部的实现类,用户无需关心,平常我们创建的组件默认角色就是 0,用于实现具体的业务逻辑。
private static BeanDefinitionHolder registerPostProcessor(BeanDefinitionRegistry registry, RootBeanDefinition definition, String beanName) {
definition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
registry.registerBeanDefinition(beanName, definition);
return new BeanDefinitionHolder(definition, beanName);
}
BeanDefinitionRegistry registry 是应用上下文,调用注册 Bean 定义方法 registerBeanDefinition,实际就是调用默认 Bean 工厂的注册 Bean 定义的方法,上面有提到默认 Bean 工厂 DefaultListableBeanFactory 核心属性 beanDefinitionMap 就是存储所有注册的 BeanDefinition。
二、初始化类路径 Bean 定义扫描器
1、注册默认注解过滤器
通过 ClassPathBeanDefinitionScanner 的构造方法,最终跳转到最后一个构造方法,核心操作是注册默认的注解扫描过滤器。
注册默认的注解过滤器,确保在组件扫描时,能够识别特定的注解。添加@Component 注解的过滤器,允许扫描带有@Component 注解的类,@Controller、@Service、@Repository 也会被扫描到。
protected void registerDefaultFilters() {
this.includeFilters.add(new AnnotationTypeFilter(Component.class));
ClassLoader cl = ClassPathScanningCandidateComponentProvider.class.getClassLoader();
try {
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) {
}
try {
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) {
}
}
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 定义(Spring 内部使用,也叫后置处理器),用于处理@Configuration、@Autowired 等注解;二是类路径 Bean 定义扫描器,用于扫描给定路径下的@Component 注解组件,将其转换为 Bean 定义。
相关免费在线工具
- Keycode 信息
查找任何按下的键的javascript键代码、代码、位置和修饰符。 在线工具,Keycode 信息在线工具,online
- Escape 与 Native 编解码
JavaScript 字符串转义/反转义;Java 风格 \uXXXX(Native2Ascii)编码与解码。 在线工具,Escape 与 Native 编解码在线工具,online
- JavaScript / HTML 格式化
使用 Prettier 在浏览器内格式化 JavaScript 或 HTML 片段。 在线工具,JavaScript / HTML 格式化在线工具,online
- JavaScript 压缩与混淆
Terser 压缩、变量名混淆,或 javascript-obfuscator 高强度混淆(体积会增大)。 在线工具,JavaScript 压缩与混淆在线工具,online
- Base64 字符串编码/解码
将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online
- Base64 文件转换器
将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online