在Spring Boot环境中,BeanFactory
和FactoryBean
这对名字相似的接口常常让开发者困惑。虽然名称相似,但它们在Spring生态中扮演着完全不同的角色。本文将结合Spring Boot特性,清晰解析它们的区别与协作。
一、BeanFactory:Spring容器的基石
核心定位 :
BeanFactory
是Spring IoC容器的基础接口,负责管理Bean的生命周期(创建、配置、依赖注入)。它是整个Spring框架的"心脏"。
在Spring Boot中的体现:
java
// Spring Boot启动类中获取BeanFactory
@SpringBootApplication
public class MyApp {
public static void main(String[] args) {
ApplicationContext ctx = SpringApplication.run(MyApp.class, args);
BeanFactory beanFactory = ctx.getAutowireCapableBeanFactory();
}
}
关键特性:
- 懒加载能力 :支持延迟初始化(通过
@Lazy
启用) - 轻量级核心:提供最基础的依赖注入功能
- 容器基础 :
ApplicationContext
是其增强实现
Spring Boot实践 :通过
ApplicationContextAware
接口可获取容器引用
二、FactoryBean:复杂对象的创建专家
核心定位 :
FactoryBean
是创建复杂对象 的特殊Bean。当从容器请求它时,实际返回的是其getObject()
方法生产的对象。
在Spring Boot中的简化实现:
java
@Component("dataSource")
public class DataSourceFactoryBean implements FactoryBean<DataSource> {
@Value("${spring.datasource.url}")
private String url;
@Override
public DataSource getObject() {
HikariConfig config = new HikariConfig();
config.setJdbcUrl(url);
return new HikariDataSource(config);
}
@Override
public Class<?> getObjectType() {
return DataSource.class;
}
}
为什么需要FactoryBean:
- 封装复杂初始化(如连接池、线程池)
- 集成第三方库(MyBatis、Redis客户端)
- 条件化创建(根据Profile创建不同实现)
- 资源管理(需要特殊清理的资源)
- 代理对象生成(AOP增强)
三、关键区别与联系(Spring Boot视角)
维度 | BeanFactory | FactoryBean |
---|---|---|
角色 | 容器核心 | 特殊Bean |
获取方式 | ctx.getBeanFactory() |
ctx.getBean("&beanName") |
使用场景 | 框架基础功能 | 复杂对象创建 |
Spring Boot集成 | 自动配置基础 | @Bean 方法的替代方案 |
协作关系:
FactoryBean
本身由BeanFactory
管理BeanFactory
通过getObject()
获取目标对象- 二者共同扩展了Spring Boot的对象创建能力
四、何时在Spring Boot中使用FactoryBean
适用场景:
-
创建复杂对象
java@Component public class ThreadPoolFactoryBean implements FactoryBean<Executor> { @Override public Executor getObject() { return Executors.newVirtualThreadPerTaskExecutor(); } }
-
集成MyBatis
Spring Boot已提供Starter,但自定义时可用:
java@Bean public SqlSessionFactoryBean sqlSessionFactory(DataSource dataSource) { SqlSessionFactoryBean factory = new SqlSessionFactoryBean(); factory.setDataSource(dataSource); return factory; }
-
环境特定实现
java@Component public class PaymentServiceFactoryBean implements FactoryBean<PaymentService> { @Autowired private Environment env; @Override public PaymentService getObject() { return "prod".equals(env.getActiveProfiles()[0]) ? new RealPaymentService() : new MockPaymentService(); } }
-
动态代理创建
java@Component public class ServiceProxyFactoryBean implements FactoryBean<Object> { @Autowired private TargetService target; @Override public Object getObject() { return Proxy.newProxyInstance(...); } }
五、Spring Boot最佳实践
1️⃣ 简化配置(注解驱动)
java
@Configuration
public class DataSourceConfig {
@Bean
public FactoryBean<DataSource> dataSource(
@Value("${datasource.url}") String url
) {
return new FactoryBean<>() {
@Override
public DataSource getObject() {
return DataSourceBuilder.create().url(url).build();
}
@Override
public Class<?> getObjectType() {
return DataSource.class;
}
};
}
}
2️⃣ 与Spring Boot特性集成
java
@Component
public class CacheFactoryBean implements FactoryBean<Cache>, InitializingBean {
@Autowired
private CacheProperties properties;
private Cache cache;
@Override
public void afterPropertiesSet() {
// 利用Boot的配置属性
this.cache = createCache(properties.getTtl());
}
@Override
public Cache getObject() {
return cache;
}
}
3️⃣ 获取FactoryBean本身
java
@SpringBootTest
class FactoryBeanTest {
@Autowired
private ApplicationContext ctx;
@Test
void getFactoryBean() {
// 获取生产的Bean
DataSource dataSource = ctx.getBean(DataSource.class);
// 获取FactoryBean本身
FactoryBean<?> factory = ctx.getBean("&dataSource", FactoryBean.class);
}
}
✅ Spring Boot专属建议:
-
优先使用
@Bean
:简单对象直接使用配置类方法java@Bean public Executor taskExecutor() { return Executors.newVirtualThreadPerTaskExecutor(); }
-
与
@Conditional
结合:实现条件化创建java@Bean @ConditionalOnMissingBean public FactoryBean<Cache> cacheFactory() { // 当不存在Cache Bean时创建 }
-
利用配置属性 :通过
@ConfigurationProperties
绑定参数java@Bean public FactoryBean<DataSource> dataSource(DataSourceProperties props) { // 使用Boot的配置属性 }
-
避免循环依赖:FactoryBean的初始化可能依赖其他Bean
六、总结:Spring Boot环境下的协作
- BeanFactory :容器引擎,管理所有Bean的生命周期
- FactoryBean :特殊工匠,负责复杂对象的创建
决策树:何时使用FactoryBean?
graph TD
A[需要创建的对象] --> B{创建过程是否复杂?}
B -->|简单| C[直接使用 @Bean]
B -->|复杂| D{是否需要动态决策?}
D -->|否| E[使用FactoryBean封装逻辑]
D -->|是| F[FactoryBean+条件判断]
Spring Boot优势整合:
- 自动配置:大部分中间件已内置FactoryBean
- 简化开发 :
@Bean
方法可替代简单FactoryBean - 生产就绪:健康检查、指标监控与FactoryBean无缝集成
经验法则 :当标准
@Bean
方法超过10行初始化代码时,考虑转换为FactoryBean
理解这对"双胞胎"的差异,能让你在Spring Boot项目中:
- 更优雅地集成复杂组件
- 编写更易维护的配置代码
- 深度掌握Spring容器的运行机制
- 有效解决第三方库集成问题
记住:BeanFactory
是舞台,FactoryBean
是特殊演员,二者共同演绎Spring Boot的精彩!