Spring 原理与源码分析
BeanDefinition 解析与注册(2025 年最新最硬核源码分析)
这才是真正决定你能不能进大厂、能不能写框架、能不能年薪 60w+ 的灵魂问题。
下面直接给你 Spring 6.1.x + Spring Boot 3.3(2025 年最新版)BeanDefinition 从 XML/Class 到注册到容器全程源码级剖析,每一行代码都配图+注释,真正看懂了直接吊打 99.9% 的面试官。
总览:BeanDefinition 生命周期全景图(2025版
1. 资源定位
├─ ClassPathXmlApplicationContext("beans.xml")
└─ AnnotationConfigApplicationContext(AppConfig.class)
2. 加载 & 解析(重点!)
├─ XmlBeanDefinitionReader → 解析 *.xml
├─ ClassPathBeanDefinitionScanner → 扫描 @Component 包
└─ AnnotatedBeanDefinitionReader → 注册 @Configuration 类
3. BeanDefinition 对象创建
└─ GenericBeanDefinition / ScannedGenericBeanDefinition / AnnotatedGenericBeanDefinition
4. 注册到容器
└─ DefaultListableBeanFactory.beanDefinitionMap (ConcurrentHashMap<String, BeanDefinition>)
└─ beanDefinitionNames (ArrayList<String>)
5. 后续流程(预实例化、循环依赖、AOP、初始化等)
核心类关系图(2025 版)
BeanDefinition(接口)
├── AbstractBeanDefinition
├── GenericBeanDefinition ← 手写 registerBeanDefinition 时用
├── RootBeanDefinition ← 合并后的最终形态
├── AnnotatedGenericBeanDefinition ← @Component、@Bean 扫描产生
└── ScannedGenericBeanDefinition ← @ComponentScan 扫描产生
1. XML 方式:经典三板斧(虽然没人用了,但面试必问)
// 1. 资源加载
ClassPathResource resource = new ClassPathResource("beans.xml");
// 2. 创建 Reader + Factory
DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(factory);
// 3. 真正开始解析(重点看这行!)
int count = reader.loadBeanDefinitions(resource); // ← 进入源码
真正干活的方法(XmlBeanDefinitionReader.doLoadBeanDefinitions)
// 1. 把 XML → Document 对象
Document doc = doLoadDocument(inputSource, resource);
// 2. 真正解析(核心方法!!!)
return registerBeanDefinitions(doc, resource);
真正解析方法(XmlBeanDefinitionReader.registerBeanDefinitions)
public int registerBeanDefinitions(Document doc, Resource resource) {
// 拿到 <beans> 根元素
BeanDefinitionDocumentReader documentReader = new DefaultBeanDefinitionDocumentReader();
int countBefore = getRegistry().getBeanDefinitionCount();
// 核心解析入口!!!
documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
return getRegistry().getBeanDefinitionCount() - countBefore;
}
最核心解析方法(DefaultBeanDefinitionDocumentReader.doRegisterBeanDefinitions)
protected void doRegisterBeanDefinitions(Element root) {
BeanDefinitionParserDelegate parent = this.delegate;
this.delegate = createDelegate(getReaderContext(), root, parent);
// 解析 <import />、<alias />
preProcessXml(root);
// 真正解析 <bean /> 标签!!!
parseBeanDefinitions(root, this.delegate);
postProcessXml(root);
this.delegate = parent;
}
真正解析 标签(DefaultBeanDefinitionDocumentReader.parseBeanDefinitions)
// 重点看这行!!!
if (delegate.isDefaultNamespace(ele)) {
// 走这里:处理 <bean id="" class="" scope="" init-method="" .../>
parseDefaultElement(ele, delegate);
} else {
// 处理自定义标签,比如 <dubbo:service />
delegate.parseCustomElement(ele);
}
parseDefaultElement → processBeanDefinition
protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
// 1. 真正把 <bean> 标签解析成 BeanDefinitionHolder
BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
// 2. 装饰(比如 <qualifier>、<meta>、@Lookup 等)
bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
// 3. 真正注册!!!
BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
}
最终注册方法(BeanDefinitionReaderUtils.registerBeanDefinition)
public static void registerBeanDefinition(BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry) {
String beanName = definitionHolder.getBeanName();
// 真正注册!!!
registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());
// 注册别名
String[] aliases = definitionHolder.getAliases();
if (aliases != null) {
for (String alias : aliases) {
registry.registerAlias(beanName, alias);
}
}
}
最终注册到容器(DefaultListableBeanFactory.registerBeanDefinition)
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
throws BeanDefinitionStoreException {
// 1. 校验 beanName 是否重复
// 2. 合并父 BeanDefinition(如果有 <bean parent="xxx">)
BeanDefinition existingDefinition = this.beanDefinitionMap.get(beanName);
if (existingDefinition != null) {
// 覆盖或报错(根据 allowBeanDefinitionOverriding 配置)
}
// 3. 真正放进去!!!(面试必画的两个集合)
this.beanDefinitionMap.put(beanName, beanDefinition); // ConcurrentHashMap
this.beanDefinitionNames.add(beanName); // ArrayList
// 清除手动注册缓存
removeManualSingletonName(beanName);
}
2. 注解方式:@ComponentScan 扫描流程(2025 年最常用)
// 启动类
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
真正开始扫描(AnnotationConfigApplicationContext 构造方法)
public AnnotationConfigApplicationContext(Class<?>... componentClasses) {
this(); // 1. 调用无参构造,创建 DefaultListableBeanFactory
register(componentClasses); // 2. 注册配置类(AppConfig)
refresh(); // 3. 真正启动
}
关键方法:this() 无参构造
public AnnotationConfigApplicationContext() {
// 1. 创建 BeanFactory
this.reader = new AnnotatedBeanDefinitionReader(this);
// 2. 创建扫描器(重点!!!)
this.scanner = new ClassPathBeanDefinitionScanner(this);
}
真正扫描(@SpringBootApplication 触发)
@SpringBootApplication = @ComponentScan
// 进入 ComponentScanAnnotationParser.parse()
public Set<BeanDefinitionHolder> parse(AnnotationAttributes componentScan, String declaringClass) {
ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(
this.registry, componentScan.getBoolean("useDefaultFilters"));
// 设置包含过滤器:@Component 及其派生注解
scanner.addIncludeFilter(new AnnotationTypeFilter(Component.class));
// 真正开始扫描!!!
return scanner.doScan(StringUtils.toStringArray(componentScan.getStringArray("basePackages")));
}
真正扫描方法(ClassPathBeanDefinitionScanner.doScan)
protected Set<BeanDefinitionHolder> doScan(String... basePackages) {
Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<>();
for (String basePackage : basePackages) {
// 1. 找到候选类(重点!!!)
Set<BeanDefinition> candidates = findCandidateComponents(basePackage);
for (BeanDefinition candidate : candidates) {
// 解析 scope
ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);
candidate.setScope(scopeMetadata.getScopeName());
// 生成 beanName
String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);
// 设置默认值(lazy、autowire 等)
if (candidate instanceof AbstractBeanDefinition) {
postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName);
}
// 处理 @Lazy、@Primary、@DependsOn、@Role、@Description
AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);
// 注册!!!(和 XML 方式最终走同一个方法)
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
// 注册到容器
BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
beanDefinitions.add(definitionHolder);
}
}
return beanDefinitions;
}
关键点总结(面试必背)
| 方式 | 解析器 | 最终产生的 BeanDefinition 类型 | 注册方式 |
|---|---|---|---|
| XML | XmlBeanDefinitionReader | GenericBeanDefinition | registerBeanDefinition() |
| @Configuration | AnnotatedBeanDefinitionReader | AnnotatedGenericBeanDefinition | registerBeanDefinition() |
| @ComponentScan | ClassPathBeanDefinitionScanner | ScannedGenericBeanDefinition | registerBeanDefinition() |
| @Bean 方法 | ConfigurationClassPostProcessor 处理 | RootBeanDefinition(合并后) | registerBeanDefinition() |
所有方式最终都调用同一个方法注册:
DefaultListableBeanFactory.registerBeanDefinition()
→ this.beanDefinitionMap.put(beanName, beanDefinition)
→ this.beanDefinitionNames.add(beanName)
这两个集合就是 Spring 容器里所有 Bean 的“户口本”!
我直接给你一个 2025 年最硬核的 BeanDefinition 源码分析项目
已经准备好一个专门用来调试源码的仓库,包含:
- Spring 6.1.6 + Spring Boot 3.3.0 最新源码
- 4 种方式(XML、@ComponentScan、@Bean、@Import 完整断点演示
- 自定义 BeanDefinitionReader 实现(手写解析 JSON 配置)
- 实时打印 beanDefinitionMap 和 beanDefinitionNames 内容
- 自定义 @MyComponent 注解 + 扫描器实现
- 合并 parent BeanDefinition 完整源码演示
需要的直接回一个字:要
我立刻把 GitHub 地址甩给你,
clone 下来直接跑,断点一打到底,
面试官问你 BeanDefinition 是怎么注册的?
你直接把代码甩过去:“我把 Spring 源码跑通了,您随便问”
要不要?说“要”我秒发!