DefaultListableBeanFactory 详解
DefaultListableBeanFactory 是 Spring IoC 容器的最核心实现,它提供了完整的 Bean 定义注册、依赖注入和生命周期管理功能。几乎所有 Spring 应用最终都依赖于这个类(包括 ApplicationContext 内部)。
一、核心作用
1. Bean 注册中心
- 维护 Bean 名称到 BeanDefinition 的映射
- 支持别名管理
- 存储 Bean 的元数据(作用域、依赖、属性等)
2. 依赖注入引擎
- 解析构造函数参数
- 通过 setter/字段注入依赖
- 处理循环依赖(三级缓存机制)
- 支持自动装配(byName, byType, constructor)
3. 生命周期管理
- 实例化 Bean
- 执行初始化方法(@PostConstruct, InitializingBean, init-method)
- 管理单例 Bean 的缓存
- 调用销毁方法(@PreDestroy, DisposableBean, destroy-method)
4. 扩展点管理
- 管理 BeanFactoryPostProcessor(容器级后置处理器)
- 管理 BeanPostProcessor(Bean 级后置处理器)
- 支持 PropertyEditorRegistrar 和 TypeConverter
二、与其他 BeanFactory 的关系
java
// 继承关系
BeanFactory (基础接口)
↑
ListableBeanFactory (可枚举)
↑
ConfigurableBeanFactory (可配置)
↑
AutowireCapableBeanFactory (可自动装配)
↑
DefaultListableBeanFactory (完整实现)
关键区别:
- BeanDefinitionRegistry :只有 DefaultListableBeanFactory 实现了此接口,支持 动态注册 Bean
- ApplicationContext:内部持有 DefaultListableBeanFactory 实例,提供额外功能(事件、资源、AOP 等)
三、核心 API 与使用示例
1. 编程式创建容器
java
// 1. 创建工厂实例
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
// 2. 创建 BeanDefinition
GenericBeanDefinition definition = new GenericBeanDefinition();
definition.setBeanClass(UserService.class);
definition.setScope(BeanDefinition.SCOPE_SINGLETON);
// 3. 设置属性(相当于 <property name="userDao" ref="userDao"/>)
MutablePropertyValues props = new MutablePropertyValues();
props.addPropertyValue("userDao", new RuntimeBeanReference("userDao"));
definition.setPropertyValues(props);
// 4. 注册 BeanDefinition
beanFactory.registerBeanDefinition("userService", definition);
// 5. 注册依赖的 Bean
beanFactory.registerBeanDefinition("userDao",
BeanDefinitionBuilder.genericBeanDefinition(UserDao.class).getBeanDefinition());
// 6. 获取 Bean 实例
UserService userService = beanFactory.getBean("userService", UserService.class);
2. 动态注册 Bean(高级用法)
java
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
// 方式一:使用 BeanDefinitionBuilder
BeanDefinitionBuilder builder = BeanDefinitionBuilder
.genericBeanDefinition(UserService.class)
.addPropertyReference("userDao", "userDao")
.setScope(BeanDefinition.SCOPE_PROTOTYPE)
.setInitMethodName("init")
.setDestroyMethodName("cleanup");
beanFactory.registerBeanDefinition("userService", builder.getBeanDefinition());
// 方式二:直接实现 FactoryBean
BeanDefinitionBuilder factoryBeanBuilder = BeanDefinitionBuilder
.genericBeanDefinition(MyFactoryBean.class);
beanFactory.registerBeanDefinition("myBean", factoryBeanBuilder.getBeanDefinition());
3. 手动处理后置处理器
java
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
// 注册 BeanFactoryPostProcessor(必须在 refresh 前)
PropertySourcesPlaceholderConfigurer configurer = new PropertySourcesPlaceholderConfigurer();
beanFactory.addBeanFactoryPostProcessor(configurer);
// 注册 BeanPostProcessor(必须在 getBean 前)
beanFactory.addBeanPostProcessor(new AutowiredAnnotationBeanPostProcessor());
beanFactory.addBeanPostProcessor(new CommonAnnotationBeanPostProcessor());
// 预实例化所有单例 Bean
beanFactory.preInstantiateSingletons();
4. 从现有配置创建
java
// 从 XML 创建
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(beanFactory);
reader.loadBeanDefinitions("classpath:applicationContext.xml");
// 从注解配置创建(需要额外依赖)
AnnotatedBeanDefinitionReader annotatedReader = new AnnotatedBeanDefinitionReader(beanFactory);
annotatedReader.register(AppConfig.class);
// 扫描包
ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(beanFactory);
scanner.scan("com.example.service");
四、核心方法速查
| 方法 | 作用 | 示例 |
|---|---|---|
registerBeanDefinition() |
注册 Bean 定义 | factory.registerBeanDefinition("user", beanDef) |
getBean() |
获取 Bean 实例 | factory.getBean(UserService.class) |
containsBeanDefinition() |
检查是否包含 Bean | factory.containsBeanDefinition("user") |
getBeansOfType() |
按类型获取所有 Bean | factory.getBeansOfType(DataSource.class) |
getBeanDefinitionNames() |
获取所有 Bean 名称 | factory.getBeanDefinitionNames() |
preInstantiateSingletons() |
预初始化所有单例 | factory.preInstantiateSingletons() |
destroySingletons() |
销毁所有单例 | factory.destroySingletons() |
registerSingleton() |
注册已存在的单例对象 | factory.registerSingleton("user", userObj) |
addBeanPostProcessor() |
添加 Bean 后置处理器 | factory.addBeanPostProcessor(processor) |
五、应用场景
1. 测试场景(精确控制)
java
public class MyServiceTest {
private DefaultListableBeanFactory factory;
@Before
public void setup() {
factory = new DefaultListableBeanFactory();
// 仅注册需要的 Bean,避免加载整个上下文
factory.registerBeanDefinition("myService",
BeanDefinitionBuilder.genericBeanDefinition(MyService.class)
.addPropertyReference("dao", "mockDao")
.getBeanDefinition());
// 注册 Mock 对象
factory.registerSingleton("mockDao", Mockito.mock(MyDao.class));
}
}
2. 动态插件系统
java
// 根据运行时条件动态注册 Bean
if (featureEnabled) {
beanFactory.registerBeanDefinition("featureService",
BeanDefinitionBuilder.genericBeanDefinition(FeatureService.class).getBeanDefinition());
}
3. 框架集成
java
// 在自定义框架中嵌入 Spring IoC
public class MyFramework {
private final DefaultListableBeanFactory beanFactory;
public MyFramework() {
this.beanFactory = new DefaultListableBeanFactory();
// 自动扫描框架内部的 Bean
new ClassPathBeanDefinitionScanner(beanFactory)
.scan("com.myframework.internal");
}
}
4. 性能优化(延迟加载)
java
// 只加载必要的 Bean,避免 ApplicationContext 的额外开销
DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(factory);
reader.loadBeanDefinitions("core-beans.xml");
// 按需加载其他模块
if (needModuleA) {
reader.loadBeanDefinitions("module-a-beans.xml");
}
六、与 ApplicationContext 的对比
| 特性 | DefaultListableBeanFactory | ApplicationContext |
|---|---|---|
| 事件发布 | ❌ 不支持 | ✅ 支持 ApplicationEvent |
| 资源访问 | ❌ 基础支持 | ✅ 统一 Resource 接口 |
| AOP 集成 | ❌ 需手动添加处理器 | ✅ 自动集成 |
| 注解支持 | ❌ 需手动注册处理器 | ✅ 自动支持 |
| 国际化 | ❌ 不支持 | ✅ 支持 MessageSource |
| 启动速度 | ⚡ 更快(功能少) | ⚡ 稍慢(功能多) |
| 内存占用 | 📊 更小 | 📊 更大 |
| 易用性 | 🛠️ 需手动配置 | 🎯 开箱即用 |
核心建议:除非有特殊需求(如性能优化、动态注册、框架集成),否则优先使用 ApplicationContext。
七、注意事项
1. 生命周期管理
java
DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
// 错误:忘记调用 preInstantiateSingletons()
factory.registerBeanDefinition(...);
// 此时单例 Bean 还未初始化!
// 正确:手动触发初始化
factory.preInstantiateSingletons();
// 错误:不管理容器关闭
// 应用结束时可能导致资源泄漏
// 正确:调用销毁方法
factory.destroySingletons(); // 销毁所有单例
// 或在 Web 环境中注册 ShutdownHook
2. 后置处理器必须手动注册
java
// ApplicationContext 会自动检测并注册,但 DefaultListableBeanFactory 不会!
// 必须手动添加常用处理器
factory.addBeanPostProcessor(new AutowiredAnnotationBeanPostProcessor()); // 处理 @Autowired
factory.addBeanPostProcessor(new CommonAnnotationBeanPostProcessor()); // 处理 @Resource @PostConstruct
factory.addBeanPostProcessor(new ApplicationContextAwareProcessor(...)); // 处理 Aware 接口
factory.addBeanPostProcessor(new AnnotationConfigUtils()); // 处理 @Configuration
// 否则注解不会生效!
3. 循环依赖处理
java
// DefaultListableBeanFactory 支持三级缓存解决单例循环依赖
// 但 prototype 作用域的 Bean 循环依赖会抛出异常
// 示例:A 依赖 B,B 依赖 A(单例:✅ 支持)
factory.registerBeanDefinition("a",
BeanDefinitionBuilder.genericBeanDefinition(A.class)
.addPropertyReference("b", "b")
.getBeanDefinition());
factory.registerBeanDefinition("b",
BeanDefinitionBuilder.genericBeanDefinition(B.class)
.addPropertyReference("a", "a")
.getBeanDefinition());
factory.preInstantiateSingletons(); // 正常完成
4. 线程安全
- Bean 注册阶段:非线程安全,应在单线程中完成所有注册
- Bean 获取阶段:线程安全,支持并发访问
java
// 推荐做法:在应用启动时完成所有注册
public class MyApp {
private static final DefaultListableBeanFactory factory;
static {
factory = new DefaultListableBeanFactory();
// 所有注册操作在这里完成
initializeFactory();
}
public static BeanFactory getBeanFactory() {
return factory; // 返回后只读
}
}
5. 内存泄漏风险
java
// 错误:频繁创建新的 Factory
public void processRequest() {
DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
// ... 加载大量 Bean
} // 无法被 GC,因为单例 Bean 持有引用
// 正确:复用工厂或使用 ApplicationContext(自动管理)
6. 配置元数据丢失
java
// 直接注册单例实例会丢失配置信息
UserService service = new UserService();
factory.registerSingleton("userService", service);
// ✅ 速度快
// ❌ 无法应用 BeanPostProcessor
// ❌ 无法处理依赖注入
// ❌ 无法调用生命周期方法
// 推荐:通过 BeanDefinition 注册
BeanDefinition definition = BeanDefinitionBuilder
.genericBeanDefinition(UserService.class)
.getBeanDefinition();
factory.registerBeanDefinition("userService", definition);
// ✅ 完整生命周期支持
7. 与 Environment 集成
java
// DefaultListableBeanFactory 没有 Environment
// 需要手动设置才能使用占位符 ${...}
StandardEnvironment env = new StandardEnvironment();
factory.setBeanExpressionResolver(new StandardBeanExpressionResolver());
// 手动添加 PropertySource
MutablePropertySources propertySources = env.getPropertySources();
propertySources.addLast(new MapPropertySource("custom", Map.of("db.url", "jdbc:...")));
// 使用 PropertySourcesPlaceholderConfigurer
PropertySourcesPlaceholderConfigurer configurer = new PropertySourcesPlaceholderConfigurer();
configurer.setEnvironment(env);
configurer.postProcessBeanFactory(factory); // 必须在所有 Bean 注册后调用
八、高级技巧
1. Bean 定义继承
java
// 创建父定义
AbstractBeanDefinition parentDef = BeanDefinitionBuilder
.genericBeanDefinition(BaseService.class)
.setAbstract(true) // 标记为抽象
.getBeanDefinition();
factory.registerBeanDefinition("baseService", parentDef);
// 创建子定义并继承
BeanDefinition childDef = BeanDefinitionBuilder
.genericBeanDefinition(UserService.class)
.setParentName("baseService") // 继承父配置
.getBeanDefinition();
factory.registerBeanDefinition("userService", childDef);
2. 自定义作用域
java
// 注册自定义作用域
factory.registerScope("tenant", new TenantScope());
// 使用自定义作用域
BeanDefinition definition = BeanDefinitionBuilder
.genericBeanDefinition(TenantConfig.class)
.setScope("tenant")
.getBeanDefinition();
factory.registerBeanDefinition("tenantConfig", definition);
3. 依赖排序
java
// 使用 @DependsOn 或手动设置
BeanDefinition definition = BeanDefinitionBuilder
.genericBeanDefinition(DatabaseService.class)
.setDependsOn("configService", "logService") // 确保顺序
.getBeanDefinition();
九、总结建议
使用 DefaultListableBeanFactory 的场景:
- ✅ 需要动态注册/卸载 Bean的插件系统
- ✅ 对启动性能有极致要求的轻量级应用
- ✅ 编写单元测试时精确控制容器内容
- ✅ 开发底层框架需要嵌入 IoC 能力
- ✅ 需要绕过 ApplicationContext 的某些默认行为
不要使用 DefaultListableBeanFactory 的场景:
- ❌ 标准 Web 应用(用 ApplicationContext)
- ❌ 需要 AOP、事务、事件等高级功能
- ❌ 希望自动处理注解配置
- ❌ 项目规模较大,需要统一资源管理
最终建议:在 99% 的场景下使用 ApplicationContext,只有当你明确知道需要绕过它的某些限制时,才考虑使用 DefaultListableBeanFactory。