IoC 容器体系 - BeanFactory vs ApplicationContext 深度解析
概述
IoC(Inversion of Control,控制反转)是 Spring 框架的核心思想,它将对象的创建、组装和管理交由容器完成,从而解耦应用程序的各个组件。Spring IoC 容器负责实例化、配置和组装 Bean,其实现体系主要分为两个层次:BeanFactory 和 ApplicationContext。
本文从源码层面深度剖析 Spring IoC 容器的继承体系、BeanDefinition 机制、容器启动时序、核心实现类的适用场景以及容器层次结构。
1. BeanFactory 与 ApplicationContext 继承体系对比
1.1 核心接口体系总览
Spring IoC 容器围绕两个核心接口展开:BeanFactory 和 ApplicationContext。前者是 IoC 容器的顶层抽象,定义了容器的基本行为;后者在其基础上扩展了企业级功能。
BeanFactory (顶层接口)
├── HierarchicalBeanFactory (父子容器能力)
│ ├── ConfigurableBeanFactory (Bean 配置能力)
│ └── ApplicationContext (完整应用上下文)
│ ├── ConfigurableApplicationContext (可配置的应用上下文)
│ │ ├── AbstractApplicationContext (模板实现)
│ │ │ ├── AbstractRefreshableApplicationContext
│ │ │ │ ├── AbstractXmlApplicationContext
│ │ │ │ │ └── ClassPathXmlApplicationContext
│ │ │ │ └── AnnotationConfigWebApplicationContext
│ │ │ └── GenericApplicationContext
│ │ │ ├── AnnotationConfigApplicationContext
│ │ │ └── GenericGroovyApplicationContext
│ │ └── ... (其他实现)
│ └── WebApplicationContext (Web 环境扩展)
├── ListableBeanFactory (可列举 Bean 的工厂)
├── AutowireCapableBeanFactory (自动装配能力)
└── DefaultListableBeanFactory (BeanFactory 的默认实现)1.2 BeanFactory 接口解析
BeanFactory 是 Spring IoC 容器的根接口,定义了获取 Bean 的通用契约:
public interface BeanFactory {
// 获取 Bean 实例(按名称)
Object getBean(String name) throws BeansException;
// 获取 Bean 实例(按类型)
<T> T getBean(Class<T> requiredType) throws BeansException;
// 获取 Bean 实例(按名称+类型,带构造参数)
<T> T getBean(String name, Class<T> requiredType) throws BeansException;
// 是否包含指定名称的 Bean
boolean containsBean(String name);
// 判断 Bean 是否为单例
boolean isSingleton(String name) throws NoSuchBeanDefinitionException;
// 判断 Bean 是否为原型
boolean isPrototype(String name) throws NoSuchBeanDefinitionException;
// 获取 Bean 的类型
Class<?> getType(String name) throws NoSuchBeanDefinitionException;
// 获取 Bean 的所有别名
String[] getAliases(String name);
}关键特点:
- 延迟初始化:Bean 仅在调用
getBean()时才被创建 - 最小化接口:只提供容器最核心的功能
- 高度抽象:不关心 Bean 如何定义和注册
1.3 ApplicationContext 接口解析
ApplicationContext 继承自 BeanFactory、ListableBeanFactory、HierarchicalBeanFactory 等多个接口,提供了更完整的企业级功能:
public interface ApplicationContext extends ListableBeanFactory,
HierarchicalBeanFactory, MessageSource, ApplicationEventPublisher, ResourcePatternResolver {
// 返回容器的唯一 ID
String getId();
// 返回容器的展示名称
String getDisplayName();
// 返回容器启动时间戳
long getStartupDate();
// 返回父容器
ApplicationContext getParent();
// 获取底层 BeanFactory(仅限内部使用)
AutowireCapableBeanFactory getAutowireCapableBeanFactory() throws IllegalStateException;
}1.4 核心差异对比
| 维度 | BeanFactory | ApplicationContext |
|---|---|---|
| Bean 实例化策略 | 延迟加载(调用 getBean 时实例化) | 预加载(容器启动时实例化所有单例 Bean) |
| 国际化支持 | 不支持 | 通过 MessageSource 支持 |
| 事件发布机制 | 不支持 | 通过 ApplicationEventPublisher 支持 |
| 资源访问 | 不支持 | 通过 ResourcePatternResolver 支持 |
| 注解支持 | 需额外配置 | 内置支持(@Autowired、@Value 等) |
| AOP 编织 | 需编程式配置 | 支持自动后置处理 |
| 典型实现 | DefaultListableBeanFactory | ClassPathXmlApplicationContext AnnotationConfigApplicationContext |
选择建议:绝大多数应用场景使用
ApplicationContext。仅在资源受限(如移动设备、嵌入式系统)或仅需最基础 IoC 功能时考虑BeanFactory。
2. BeanDefinition 注册、合并与别名机制
2.1 BeanDefinition 结构
BeanDefinition 是 Spring IoC 容器构建 Bean 实例的"蓝图",描述了 Bean 的所有元数据信息:
public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement {
// Bean 作用域
void setScope(@Nullable String scope);
String getScope();
// Bean 的类名
void setBeanClassName(@Nullable String beanClassName);
@Nullable
String getBeanClassName();
// 是否延迟初始化
void setLazyInit(boolean lazyInit);
boolean isLazyInit();
// 依赖信息
void setDependsOn(@Nullable String... dependsOn);
@Nullable
String[] getDependsOn();
// 自动装配模式
void setAutowireMode(int autowireMode);
int getAutowireMode();
// 初始化和销毁方法
void setInitMethodName(@Nullable String initMethodName);
@Nullable
String getInitMethodName();
void setDestroyMethodName(@Nullable String destroyMethodName);
@Nullable
String getDestroyMethodName();
// 构造函数参数
ConstructorArgumentValues getConstructorArgumentValues();
// 属性值
MutablePropertyValues getPropertyValues();
// 工厂方法
void setFactoryBeanName(@Nullable String factoryBeanName);
void setFactoryMethodName(@Nullable String factoryMethodName);
// 角色(应用/基础设施/复合)
int getRole();
// 父 BeanDefinition 名称
void setParentName(@Nullable String parentName);
@Nullable
String getParentName();
}BeanDefinition 的角色分类:
| 角色常量 | 值 | 说明 |
|---|---|---|
ROLE_APPLICATION | 0 | 用户定义的应用程序 Bean |
ROLE_SUPPORT | 1 | 复杂配置的支持 Bean |
ROLE_INFRASTRUCTURE | 2 | Spring 内部基础设施 Bean |
2.2 BeanDefinition 注册机制
BeanDefinition 的注册入口是 BeanDefinitionRegistry 接口:
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);
// 获取所有 BeanDefinition 名称
String[] getBeanDefinitionNames();
// 获取 BeanDefinition 数量
int getBeanDefinitionCount();
// 是否正在使用指定 Bean 名称
boolean isBeanNameInUse(String beanName);
}常见注册方式:
方式一:基于 XML 配置
<beans>
<bean id="userService" class="com.example.UserService">
<property name="userDao" ref="userDao"/>
</bean>
</beans>方式二:基于注解(@Component + @ComponentScan)
@Component
public class UserService {
@Autowired
private UserDao userDao;
}方式三:基于 @Bean 注解
@Configuration
public class AppConfig {
@Bean
public UserService userService() {
return new UserService(userDao());
}
@Bean
public UserDao userDao() {
return new UserDao();
}
}方式四:编程式注册
// 创建 DefaultListableBeanFactory
DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
// 创建 BeanDefinition
AbstractBeanDefinition bd = BeanDefinitionBuilder
.genericBeanDefinition(UserService.class)
.setScope(BeanDefinition.SCOPE_SINGLETON)
.addPropertyValue("userDao", new UserDao())
.getBeanDefinition();
// 注册到容器
factory.registerBeanDefinition("userService", bd);2.3 BeanDefinition 合并机制
在实际应用中,Bean 定义常存在继承关系。Spring 通过 AbstractBeanFactory.getMergedBeanDefinition() 方法将父 BeanDefinition 与子 BeanDefinition 合并为一个完整的 RootBeanDefinition。
配置示例:
<bean id="baseDao" class="com.example.BaseDao" abstract="true">
<property name="dataSource" ref="dataSource"/>
</bean>
<bean id="userDao" class="com.example.UserDao" parent="baseDao">
<property name="tableName" value="users"/>
</bean>合并流程:
1. 检查本地缓存中是否已存在合并后的 BeanDefinition
2. 如果存在,直接返回缓存结果
3. 如果不存在,获取父 BeanDefinition
4. 生成新的 RootBeanDefinition 实例
5. 将父 BeanDefinition 的属性复制到合并后的实例
6. 用子 BeanDefinition 的属性覆盖父 BeanDefinition 的属性
7. 缓存合并后的 BeanDefinition
8. 返回合并结果合并的关键源码 (AbstractBeanFactory.getMergedBeanDefinition()):
private RootBeanDefinition getMergedBeanDefinition(
String beanName, BeanDefinition bd, BeanDefinition containingBd)
throws BeanDefinitionStoreException {
synchronized (this.mergedBeanDefinitions) {
RootBeanDefinition mbd = null;
RootBeanDefinition previous = null;
// 1. 先检查缓存
previous = this.mergedBeanDefinitions.get(beanName);
if (previous != null) {
return previous;
}
// 2. 处理父 BeanDefinition
if (bd.getParentName() == null) {
// 没有父定义,直接封装
if (bd instanceof RootBeanDefinition) {
mbd = ((RootBeanDefinition) bd).cloneBeanDefinition();
} else {
mbd = new RootBeanDefinition(bd);
}
} else {
// 有父定义,递归合并
BeanDefinition pbd;
try {
String parentBeanName = bd.getParentName();
pbd = getMergedBeanDefinition(parentBeanName);
} catch (BeansException ex) {
throw new BeanDefinitionStoreException(bd.getResourceDescription(),
beanName, "Cannot resolve bean definition parent", ex);
}
// 以父定义为模板创建新的 RootBeanDefinition
mbd = new RootBeanDefinition(pbd);
// 用子定义覆盖父定义
mbd.overrideFrom(bd);
}
// 3. 缓存合并后的结果
this.mergedBeanDefinitions.put(beanName, mbd);
return mbd;
}
}2.4 别名机制
Spring 允许为一个 Bean 定义多个名称(别名),通过 AliasRegistry 接口实现:
// 编程式注册别名
BeanDefinitionRegistry registry = ...;
registry.registerAlias("userService", "userServiceAlias");
registry.registerAlias("userService", "userServiceImpl");
// XML 配置别名
<bean id="userService" name="userServiceAlias, userServiceImpl" class="..."/>
// 或使用 <alias> 标签
<alias name="userService" alias="userServiceImpl"/>别名设计要点:
- 别名允许在统一 Bean 在不同上下文中使用不同名称
- 别名解析采用链式机制(一个别名可指向另一个别名)
- 别名生命周期与 Bean 定义生命周期绑定
// SimpleAliasRegistry 别名解析核心逻辑
public class SimpleAliasRegistry implements AliasRegistry {
private final Map<String, String> aliasMap = new ConcurrentHashMap<>(16);
@Override
public void registerAlias(String name, String alias) {
synchronized (this.aliasMap) {
// 验证名称和别名不能相同
if (alias.equals(name)) {
this.aliasMap.remove(alias);
return;
}
// 检查别名冲突
String registeredName = this.aliasMap.get(alias);
if (registeredName != null) {
if (registeredName.equals(name)) {
return; // 别名已存在
}
// 是否允许覆盖
if (!allowAliasOverriding()) {
throw new IllegalStateException("Cannot register alias...");
}
}
// 检查循环引用
checkForAliasCircle(name, alias);
this.aliasMap.put(alias, name);
}
}
// 解析别名链,返回最终的规范名称
public String canonicalName(String name) {
String canonicalName = name;
String resolvedName;
// 循环解析,直到别名不再被映射
do {
resolvedName = this.aliasMap.get(canonicalName);
if (resolvedName != null) {
canonicalName = resolvedName;
}
} while (resolvedName != null);
return canonicalName;
}
}3. 容器启动时序(refresh() 流程关键步骤)
3.1 启动入口
无论是 XML 配置还是注解配置,AbstractApplicationContext.refresh() 是所有 ApplicationContext 容器启动的统一入口。该方法定义了 IoC 容器初始化的完整模板流程。
3.2 refresh() 12 步流程精讲
@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// Step 1: 准备刷新,设置启动时间、激活标志位
prepareRefresh();
// Step 2: 获取新的 BeanFactory(模板方法,子类实现)
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// Step 3: 准备 BeanFactory,设置类加载器、后置处理器等
prepareBeanFactory(beanFactory);
try {
// Step 4: 子类扩展点,允许在 Bean 初始化前修改 BeanFactory
postProcessBeanFactory(beanFactory);
// Step 5: 调用 BeanFactoryPostProcessor
invokeBeanFactoryPostProcessors(beanFactory);
// Step 6: 注册 BeanPostProcessor
registerBeanPostProcessors(beanFactory);
// Step 7: 初始化 MessageSource(国际化)
initMessageSource();
// Step 8: 初始化 ApplicationEventMulticaster(事件广播器)
initApplicationEventMulticaster();
// Step 9: 子类扩展点,初始化特定上下文中的特殊 Bean
onRefresh();
// Step 10: 注册 ApplicationListener
registerListeners();
// Step 11: 完成 BeanFactory 初始化,实例化所有单例 Bean
finishBeanFactoryInitialization(beanFactory);
// Step 12: 发布容器刷新完成事件
finishRefresh();
}
catch (BeansException ex) {
// 回滚 - 销毁已创建的单例 Bean
destroyBeans();
// 重置活动标志
cancelRefresh(ex);
throw ex;
}
finally {
// 重置 Spring 3.0 引入的通用缓存
resetCommonCaches();
}
}
}Step 1:prepareRefresh()
protected void prepareRefresh() {
this.startupDate = System.currentTimeMillis(); // 设置启动时间
this.closed.set(false); // 取消关闭标志
this.active.set(true); // 设置活动标志
// 留给子类:初始化属性源(PropertySource)
initPropertySources();
// 验证所有必需的属性是否存在
getEnvironment().validateRequiredProperties();
}Step 2:obtainFreshBeanFactory()
这是模板方法模式的关键应用——不同的子类在此返回不同类型的 BeanFactory:
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
// 子类实现:刷新 BeanFactory,销毁旧的 BeanFactory
refreshBeanFactory();
// 返回刷新后的 BeanFactory 实例
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
return beanFactory;
}以 AbstractRefreshableApplicationContext 为例:
@Override
protected final void refreshBeanFactory() throws BeansException {
if (hasBeanFactory()) {
// 如果已有 BeanFactory,销毁所有 Bean 并关闭
destroyBeans();
closeBeanFactory();
}
try {
// 创建一个新的 DefaultListableBeanFactory
DefaultListableBeanFactory beanFactory = createBeanFactory();
beanFactory.setSerializationId(getId());
// 自定义 BeanFactory(设置是否允许 Bean 覆盖、循环引用等)
customizeBeanFactory(beanFactory);
// 加载 BeanDefinition(关键步骤,子类实现)
loadBeanDefinitions(beanFactory);
synchronized (this.beanFactoryMonitor) {
this.beanFactory = beanFactory;
}
}
catch (IOException ex) {
throw new ApplicationContextException("...");
}
}Step 3:prepareBeanFactory()
配置 BeanFactory 的标准特性:
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
// 设置类加载器
beanFactory.setBeanClassLoader(getClassLoader());
// 设置 SpEL 表达式解析器
beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver());
// 注册默认的 PropertyEditor
beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));
// 添加 ApplicationContextAwareProcessor —— 处理 Aware 回调
beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
// 忽略以下接口的自动装配 —— 这些依赖通过容器注入而非自动装配
beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);
// 注册可解析的依赖类型(当 @Autowired 依赖这些类型时,容器自动注入对应实例)
beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
beanFactory.registerResolvableDependency(ResourceLoader.class, this);
beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
beanFactory.registerResolvableDependency(ApplicationContext.class, this);
// 注册早期后置处理器 —— 检测 ApplicationListener
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));
// 注册环境相关的 Bean
if (!beanFactory.containsBean(ENVIRONMENT_BEAN_NAME)) {
beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());
}
if (!beanFactory.containsBean(SYSTEM_PROPERTIES_BEAN_NAME)) {
beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());
}
if (!beanFactory.containsBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());
}
}Step 5:invokeBeanFactoryPostProcessors()
这个步骤是所有 BeanFactoryPostProcessor 执行的入口,是 Spring 留给外部扩展的关键点:
protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
// 兼容旧版本:如果 BeanFactory 检测到 LoadTimeWeaver 则自动注册
if (beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
}
}执行顺序(严格优先级):
- 已注册的
BeanDefinitionRegistryPostProcessor(实现PriorityOrdered接口) - 已注册的
BeanDefinitionRegistryPostProcessor(实现Ordered接口) - 其他已注册的
BeanDefinitionRegistryPostProcessor - 经
BeanDefinitionRegistryPostProcessor新发现的所有BeanDefinitionRegistryPostProcessor(递归执行) - 已注册的
BeanFactoryPostProcessor(实现PriorityOrdered接口) - 已注册的
BeanFactoryPostProcessor(实现Ordered接口) - 其他已注册及新发现的
BeanFactoryPostProcessor
Step 11:finishBeanFactoryInitialization()
预实例化所有非延迟初始化的单例 Bean:
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
// 设置 ConversionService(类型转换服务)
if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME)
&& beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {
beanFactory.setConversionService(
beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));
}
// 注册默认的嵌入值解析器(处理 @Value 注解)
if (!beanFactory.hasEmbeddedValueResolver()) {
beanFactory.addEmbeddedValueResolver(str -> getEnvironment().resolvePlaceholders(str));
}
// 初始化 LoadTimeWeaverAware Bean
String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
for (String weaverAwareName : weaverAwareNames) {
getBean(weaverAwareName);
}
// 停止使用临时类加载器
beanFactory.setTempClassLoader(null);
// 冻结配置 —— 禁止修改 BeanDefinition
beanFactory.freezeConfiguration();
// 实例化所有剩余的单例 Bean(核心逻辑)
beanFactory.preInstantiateSingletons();
}DefaultListableBeanFactory.preInstantiateSingletons() 详解:
@Override
public void preInstantiateSingletons() throws BeansException {
// 获取所有 BeanDefinition 名称的快照
List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);
// 触发所有非延迟初始化的单例 Bean 的实例化
for (String beanName : beanNames) {
RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
if (!mbd.isAbstract() && mbd.isSingleton() && !mbd.isLazyInit()) {
// 处理 FactoryBean
if (isFactoryBean(beanName)) {
// 先获取 FactoryBean 实例(加 & 前缀)
Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
if (mbd.isEagerInit()) {
getBean(beanName);
}
} else {
getBean(beanName);
}
}
}
// 所有单例 Bean 实例化后,触发 SmartInitializingSingleton 回调
for (String beanName : beanNames) {
Object singletonInstance = getSingleton(beanName);
if (singletonInstance instanceof SmartInitializingSingleton) {
SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
smartSingleton.afterSingletonsInstantiated();
}
}
}3.3 refresh() 流程图
┌─────────────────────────────────────┐
│ refresh() 入口 │
└──────────────────┬──────────────────┘
▼
┌──────────────────────────────────────────────────────────────────┐
│ 1. prepareRefresh() —— 准备环境、验证必需属性 │
├──────────────────────────────────────────────────────────────────┤
│ 2. obtainFreshBeanFactory() —— 创建/刷新 BeanFactory,加载定义 │
├──────────────────────────────────────────────────────────────────┤
│ 3. prepareBeanFactory() —— 设置类加载器、忽略接口等 │
├──────────────────────────────────────────────────────────────────┤
│ 4. postProcessBeanFactory() —— 【子类扩展点】修改 BeanFactory │
├──────────────────────────────────────────────────────────────────┤
│ 5. invokeFactoryPostProcess()—— 执行 BeanFactoryPostProcessor │
│ ├── BeanDefinitionRegistryPostProcessor (PriorityOrdered) │
│ ├── BeanDefinitionRegistryPostProcessor (Ordered) │
│ ├── BeanDefinitionRegistryPostProcessor (其他) │
│ └── BeanFactoryPostProcessor │
├──────────────────────────────────────────────────────────────────┤
│ 6. registerBeanPostProcessors()—— 注册 BeanPostProcessor │
├──────────────────────────────────────────────────────────────────┤
│ 7. initMessageSource() —— 初始化国际化组件 │
├──────────────────────────────────────────────────────────────────┤
│ 8. initApplicationEventMulticaster() —— 初始化事件广播器 │
├──────────────────────────────────────────────────────────────────┤
│ 9. onRefresh() —— 【子类扩展点】特殊 Bean 初始化 │
├──────────────────────────────────────────────────────────────────┤
│10. registerListeners() —— 注册 ApplicationListener │
├──────────────────────────────────────────────────────────────────┤
│11. finishBeanFactoryInit() —— 实例化所有单例 Bean │
│ ├── freezeConfiguration() │
│ └── preInstantiateSingletons() │
├──────────────────────────────────────────────────────────────────┤
│12. finishRefresh() —— 发布 ContextRefreshedEvent │
└──────────────────────────────────────────────────────────────────┘4. 源码精读:DefaultListableBeanFactory.registerBeanDefinition()
DefaultListableBeanFactory 是 Spring IoC 容器中最核心的实现类,registerBeanDefinition() 是向容器注册 Bean 定义的入口方法。以下逐行分析其实现:
// 文件:DefaultListableBeanFactory.java
// 版本:Spring Framework 5.3.x
@Override
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
throws BeanDefinitionStoreException {
// ──── 第1段:参数校验 ────
// 1.1 BeanName 不能为空 —— 这是注册的前提条件
Assert.hasText(beanName, "Bean name must not be empty");
// 1.2 BeanDefinition 实例不能为空
Assert.notNull(beanDefinition, "BeanDefinition must not be null");
// 1.3 BeanDefinition 必须是有效的实现类型
// 这里确保传入的 BeanDefinition 在经过验证后再注册
if (beanDefinition instanceof AbstractBeanDefinition) {
try {
// validate() 方法检查 BeanDefinition 的合法性:
// - 如果 methodOverrides 与构造方法注入同时使用,将抛出异常
// - 因为 lookup-method/replaced-method 与构造器注入不能共存
((AbstractBeanDefinition) beanDefinition).validate();
}
catch (BeanDefinitionValidationException ex) {
throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(),
beanName, "Validation of bean definition failed", ex);
}
}
// ──── 第2段:检查 BeanName 冲突 ────
// 2.1 查找是否已有同名 BeanDefinition 存在
BeanDefinition existingDefinition = this.beanDefinitionMap.get(beanName);
// 2.2 如果已存在同名定义
if (existingDefinition != null) {
// 2.2.1 检查是否允许覆盖 —— 默认允许覆盖
if (!isAllowBeanDefinitionOverriding()) {
// 当不允许覆盖时抛出异常
throw new BeanDefinitionOverrideException(beanName, beanDefinition, existingDefinition);
}
// 2.2.2 记录覆盖日志(不同级别的日志取决于新旧定义的来源)
// - 若新定义来自同一资源且角色不同,记录 DEBUG 级别
// - 若新定义来自不同资源,记录 INFO 级别
// - 若新定义覆盖了基础设施 Bean,记录 WARN 级别
else if (existingDefinition.getRole() < beanDefinition.getRole()) {
// 用用户定义覆盖基础设施 Bean — 记录 INFO
if (logger.isInfoEnabled()) {
logger.info("Overriding user-defined bean definition for bean '" + beanName +
"' with a framework-generated bean definition: replacing [" +
existingDefinition + "] with [" + beanDefinition + "]");
}
}
else if (!beanDefinition.equals(existingDefinition)) {
// 新定义与现有定义不同 — 记录 INFO
if (logger.isInfoEnabled()) {
logger.info("Overriding bean definition for bean '" + beanName +
"' with a different definition: replacing [" +
existingDefinition + "] with [" + beanDefinition + "]");
}
}
else {
// 新定义与现有定义相同 — 记录 DEBUG
if (logger.isDebugEnabled()) {
logger.debug("Overriding bean definition for bean '" + beanName +
"' with an equivalent definition: replacing [" +
existingDefinition + "] with [" + beanDefinition + "]");
}
}
// 2.2.3 执行覆盖:将新 BeanDefinition 放入 beanDefinitionMap
this.beanDefinitionMap.put(beanName, beanDefinition);
}
// 2.3 不存在同名定义 — 首次注册
else {
// 2.3.1 检查是否已有 Bean 被创建(即容器已开始实例化)
// 如果其他 Bean 的创建过程中已经通过 getBean() 触发了
// 该 Bean 的早期访问,此时再注册新定义是不安全的
if (hasBeanCreationStarted()) {
// 容器创建阶段已开始 — 需要同步处理
synchronized (this.beanDefinitionMap) {
// 注册 BeanDefinition
this.beanDefinitionMap.put(beanName, beanDefinition);
// 更新所有 Bean 名称列表
List<String> updatedDefinitions = new ArrayList<>(this.beanDefinitionNames.size() + 1);
updatedDefinitions.addAll(this.beanDefinitionNames);
updatedDefinitions.add(beanName);
this.beanDefinitionNames = updatedDefinitions;
// 如果手动注册的单例列表中已存在该名称,移除它
// (单例注册优先级低于 BeanDefinition 注册)
if (this.manualSingletonNames.contains(beanName)) {
Set<String> updatedSingletons = new LinkedHashSet<>(this.manualSingletonNames);
updatedSingletons.remove(beanName);
this.manualSingletonNames = updatedSingletons;
}
}
}
// 2.3.2 容器尚未开始创建 Bean — 直接更新(无需同步)
else {
this.beanDefinitionMap.put(beanName, beanDefinition);
this.beanDefinitionNames.add(beanName);
this.manualSingletonNames.remove(beanName);
}
// 2.3.3 清除 frozenBeanDefinitionNames 缓存
// (冻结后此字段非空,清除以触发下次重新生成)
this.frozenBeanDefinitionNames = null;
}
// ──── 第3段:处理已存在的单例缓存 ────
// 3.1 如果该 Bean 名称在之前的单例缓存中存在
// (可能因为早期引用导致单例被提前创建)
if (existingDefinition != null || containsSingleton(beanName)) {
// 3.2 清除合并后的 BeanDefinition 缓存
// 因为 BeanDefinition 已被替换,合并后的缓存已经过时
resetBeanDefinition(beanName);
}
}关键设计要点总结
| 代码段 | 设计意图 |
|---|---|
| 参数校验 | 确保注册的输入参数合法,防止后续操作中出现 NPE 或其他不可预期的错误 |
| BeanDefinition 验证 | 提前捕获不兼容的配置组合(如 lookup-method 与构造器注入冲突),尽早失败 |
| 覆盖控制 | 通过 allowBeanDefinitionOverriding 开关控制是否允许覆盖现有定义,默认允许 |
| 差异化日志 | 根据新旧定义的角色和内容差异,输出不同级别的日志,帮助运维排障 |
| 并发安全 | 使用 synchronized 保证容器启动过程中的并发注册安全 |
| 缓存一致性 | 更新 beanDefinitionMap 的同时同步维护 beanDefinitionNames 和 manualSingletonNames,保证数据一致性 |
| 缓存失效 | 更新 frozenBeanDefinitionNames 并调用 resetBeanDefinition() 清除衍生缓存 |
5. 各 ApplicationContext 实现适用场景
5.1 ClassPathXmlApplicationContext
设计目的:从类路径加载 XML 配置文件,是最传统的 ApplicationContext 实现之一。
// 从单个 XML 文件加载
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
// 从多个 XML 文件加载
ApplicationContext ctx = new ClassPathXmlApplicationContext(
"service-context.xml", "dao-context.xml", "security-context.xml");
// 带父子容器
ApplicationContext parent = new ClassPathXmlApplicationContext("parent-context.xml");
ApplicationContext child = new ClassPathXmlApplicationContext(
new String[]{"child-context.xml"}, parent);内部原理:
public class ClassPathXmlApplicationContext extends AbstractXmlApplicationContext {
// 构造函数链最终调用 refresh()
public ClassPathXmlApplicationContext(String configLocation) throws BeansException {
this(new String[] {configLocation}, true, null);
}
public ClassPathXmlApplicationContext(
String[] configLocations, boolean refresh, @Nullable ApplicationContext parent)
throws BeansException {
super(parent);
setConfigLocations(configLocations); // 设置配置文件路径
if (refresh) {
refresh(); // 启动容器
}
}
}适用场景:
- 传统 XML 配置的 Spring 项目
- 遗留系统维护
- 需要细粒度 Bean 定义控制的场景
- 学习 Spring 原理时的测试环境
5.2 AnnotationConfigApplicationContext
设计目的:基于注解和 Java Config 的应用上下文,是现代 Spring 应用的首选实现。
// 使用 @Configuration 类
ApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class);
// 使用包扫描路径
ApplicationContext ctx = new AnnotationConfigApplicationContext("com.example");
// 同时使用配置类和扫描路径
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
ctx.register(AppConfig.class, SecurityConfig.class);
ctx.scan("com.example.service", "com.example.dao");
ctx.refresh();
// 获取 Bean
UserService userService = ctx.getBean(UserService.class);注册配置类的流程:
// AnnotationConfigApplicationContext 的关键构造函数
public class AnnotationConfigApplicationContext extends GenericApplicationContext
implements AnnotationConfigRegistry {
// 注解 Bean 定义读取器(处理 @Bean 方法)
private final AnnotatedBeanDefinitionReader reader;
// 类路径 Bean 定义扫描器(处理 @ComponentScan)
private final ClassPathBeanDefinitionScanner scanner;
public AnnotationConfigApplicationContext() {
// 初始化 reader —— 注册内部后置处理器(ConfigurationClassPostProcessor 等)
this.reader = new AnnotatedBeanDefinitionReader(this);
// 初始化 scanner —— 用于包扫描
this.scanner = new ClassPathBeanDefinitionScanner(this);
}
public AnnotationConfigApplicationContext(Class<?>... componentClasses) {
this();
// 注册配置类
register(componentClasses);
// 触发 refresh() 启动容器
refresh();
}
@Override
public void register(Class<?>... componentClasses) {
for (Class<?> componentClass : componentClasses) {
this.reader.register(componentClass);
}
}
@Override
public void scan(String... basePackages) {
this.scanner.scan(basePackages);
}
}适用场景:
- 所有基于注解的现代 Spring 项目
- Spring Boot 项目(底层使用 AnnotationConfigApplicationContext)
- 微服务架构中的服务模块
- 无需 XML 配置的纯 Java 配置项目
5.3 AnnotationConfigWebApplicationContext
设计目的:Web 环境下的注解配置应用上下文,是 Spring MVC / Spring Boot Web 应用的容器实现。
// 在 web.xml 中配置
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextClass</param-name>
<param-value>
org.springframework.web.context.support.AnnotationConfigWebApplicationContext
</param-value>
</init-param>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>com.example.WebConfig</param-value>
</init-param>
</servlet>// 编程式配置(Spring Boot 内部使用)
AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
context.setConfigLocation("com.example.config");
context.setServletContext(servletContext);
context.refresh();适用场景:
- Spring MVC 传统 Web 项目(非 Spring Boot)
- 需要与 Servlet 容器深度集成的场景
- 需要在 Web 应用中使用
WebApplicationContext的扩展功能
5.4 FileSystemXmlApplicationContext
// 从文件系统路径加载
ApplicationContext ctx = new FileSystemXmlApplicationContext(
"D:/config/applicationContext.xml");
// 相对路径(相对于当前工作目录)
ApplicationContext ctx = new FileSystemXmlApplicationContext(
"config/applicationContext.xml");适用场景:
- XML 配置文件在文件系统而非类路径中的场景
- 桌面应用或独立服务器应用
- 需要热加载配置文件(配合自定义实现)
5.5 GenericApplicationContext
// 创建一个空的容器,然后编程式注册 BeanDefinition
GenericApplicationContext ctx = new GenericApplicationContext();
// 通过 reader 注册
XmlBeanDefinitionReader xmlReader = new XmlBeanDefinitionReader(ctx);
xmlReader.loadBeanDefinitions("classpath:applicationContext.xml");
// 或通过编程方式
ctx.registerBeanDefinition("myBean", BeanDefinitionBuilder
.genericBeanDefinition(MyBean.class)
.getBeanDefinition());
// 必须手动调用 refresh()
ctx.refresh();适用场景:
- 需要精细控制容器创建过程的场景
- 用于测试框架(如 Spring TestContext Framework)
- 需要集成多种 Bean 定义来源的场景
5.6 实现类选型对比
| 实现类 | 配置方式 | 启动方式 | 主要使用场景 |
|---|---|---|---|
ClassPathXmlApplicationContext | XML 文件 | 构造函数自动 refresh | 传统 XML 项目 |
AnnotationConfigApplicationContext | 注解/@Configuration | 构造函数自动 refresh | 现代注解项目、Spring Boot |
AnnotationConfigWebApplicationContext | 注解/@Configuration | 需手动 refresh | Spring MVC 传统 Web |
FileSystemXmlApplicationContext | XML 文件(文件系统) | 构造函数自动 refresh | 非类路径 XML 配置 |
GenericApplicationContext | 编程式/任意方式 | 需手动 refresh | 工具类、测试框架 |
AbstractRefreshableWebApplicationContext | 多种方式 | 需手动 refresh | Web 应用的灵活配置 |
6. 容器层次结构(父子容器)
6.1 父子容器的设计动机
Spring 允许容器之间存在层次关系:子容器可以访问父容器中的 Bean,但父容器不能访问子容器中的 Bean。这一设计的主要目的是:
- 模块化隔离:不同模块使用不同的容器,避免 Bean 名称冲突
- 公共 Bean 复用:父容器定义公共基础设施(数据源、事务管理器等)
- AOP 代理隔离:子容器的 AOP 配置不影响父容器中的 Bean
- 作用域边界:Web 应用中,根容器与 Servlet 容器分离
6.2 核心接口:HierarchicalBeanFactory
public interface HierarchicalBeanFactory extends BeanFactory {
// 返回父 BeanFactory
BeanFactory getParentBeanFactory();
// 当前容器是否包含指定名称的 Bean(不向上搜索父容器)
boolean containsLocalBean(String name);
}6.3 父子容器的 Bean 查找逻辑
AbstractBeanFactory 中 getBean() 的查找机制:
// AbstractBeanFactory 的层次查找逻辑
public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport
implements ConfigurableBeanFactory {
@Override
public <T> T getBean(String name, Class<T> requiredType) throws BeansException {
// 实际执行 doGetBean
return doGetBean(name, requiredType, null, false);
}
protected <T> T doGetBean(...) {
// 1. 尝试从当前容器的单例缓存中获取
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
// 缓存命中,直接返回
beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, null);
} else {
// 2. 检查当前容器是否包含此 BeanDefinition
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
// 3. 检查父容器 — 这是层次查找的关键
BeanFactory parentBeanFactory = getParentBeanFactory();
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
// 当前容器不包含该 Bean 定义,委托给父容器
String parentBeanName = transformedBeanName(name);
if (parentBeanFactory instanceof AbstractBeanFactory) {
return ((AbstractBeanFactory) parentBeanFactory).doGetBean(...);
} else if (parentBeanFactory instanceof ConfigurableBeanFactory) {
return parentBeanFactory.getBean(parentBeanName, requiredType);
}
}
// 4. 创建 Bean 实例(如果当前容器有定义)
// ... 创建逻辑
}
return (T) beanInstance;
}
}查找优先级:
1. 当前容器缓存 →
2. 当前容器 BeanDefinition →
3. 父容器递归查找 →
4. 抛出 NoSuchBeanDefinitionException