Spring 的简单工厂模式通过 BeanFactory 和工厂方法配置,将对象创建逻辑从业务代码中解耦。它不仅是 Spring IoC 容器的基石(如 getBean() 方法),也是灵活管理多环境配置(如多数据源、国际化)的核心手段。尽管简单工厂模式在扩展性上存在局限,但在 Spring 的配置驱动和条件化 Bean 机制加持下,依然能实现高度灵活的对象治理。掌握工厂方法与容器生命周期的协同,是构建可维护 Spring 应用的关键技能。
1. Spring 简单工厂模式的核心特点
集中式对象创建:通过一个工厂类统一管理对象的创建逻辑,隐藏实例化细节。
条件分支控制:根据输入参数(如名称、类型)动态选择具体实现类。
与 IoC 容器集成:Spring 通过 BeanFactory 和静态/实例工厂方法实现类似简单工厂的功能。
配置驱动:通过 XML 或注解定义工厂逻辑,无需硬编码条件判断。
2. Spring 版本与源码获取
版本:Spring Framework 5.3.26(长期支持版本)
源码下载:
Maven 依赖:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.3.26</version>
</dependency>
直接下载地址:Spring Framework 5.3.26 Release
调试技巧:
- 关键断点位置:DefaultListableBeanFactory.getBean() → createBean() → instantiateBean()。
- 观察静态工厂方法调用栈:SimpleInstantiationStrategy.instantiate()。
3. 源码级实现剖析
简单工厂像一个“自动售货机”,投币(输入参数)后,机器根据商品编号(条件)自动分配对应饮料(对象实例)。
// Spring 内置静态工厂示例:Calendar 对象创建
public abstract class Calendar {
public static Calendar getInstance() {
return createCalendar(TimeZone.getDefault(), Locale.getDefault());
}
// 根据时区和地区选择具体实现类(如 GregorianCalendar)
private static Calendar createCalendar(TimeZone zone, Locale locale) {
// 条件分支选择具体实现
if (locale.getUnicodeLocaleType("ca") == null) {
return new GregorianCalendar(zone, locale);
}
// 其他日历类型分支...
}
}
// Spring 工厂方法配置对应实现
public class StaticCalendarFactory {
public static Calendar createCalendar() {
return Calendar.getInstance();
}
}
4. 简单工厂模式的多维度应用
配置方式对比
- XML 静态工厂:
<bean id="calendar"
class="org.springframework.beans.factory.config.StaticCalendarFactory"
factory-method="createCalendar"/>
- XML 实例工厂:
<bean id="carFactory" class="com.example.CarFactory"/>
<bean id="tesla" factory-bean="carFactory" factory-method="createCar">
<constructor-arg value="tesla"/>
</bean>
- 注解配置:
@Configuration
public class AppConfig {
@Bean
public Car tesla() {
return CarFactory.createCar("tesla"); // 静态工厂方法
}
}
Spring 内置工厂类
工厂类 | 作用 |
StaticListableBeanFactory | 基于静态 Map 存储 Bean 定义的简单工厂 |
PropertiesBeanDefinitionReader | 从 Properties 文件读取 Bean 定义的工厂 |
StaticMethodMatcherPointcutAdvisor | 通过静态方法创建 AOP 通知的工厂 |
5. 简单工厂模式 vs 其他模式
场景 | 简单工厂模式 | 工厂方法模式 | 抽象工厂模式 |
创建逻辑复杂度 | 单一工厂类,条件分支创建对象 | 每个产品一个工厂类 | 每个产品族一个工厂类 |
扩展性 | 需修改工厂类添加新产品 | 新增产品只需扩展工厂接口 | 新增产品族需扩展抽象工厂 |
Spring 典型应用 | BeanFactory.getBean() 按名称创建对象 | FactoryBean 接口实现 | 无直接对应,需自定义实现 |
6. 实际应用场景
多数据源动态切换:
public class DataSourceFactory {
public static DataSource getDataSource(String env) {
return env.equals("prod") ?
new HikariProdDataSource() : new BasicDevDataSource();
}
}
国际化消息解析:
<bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
<property name="basenames">
<list>
<value>messages_#{systemProperties['user.language']}</value>
</list>
</property>
</bean>
条件化 Bean 创建:
@Bean
@ConditionalOnClass(name = "com.example.RedisClient")
public CacheService redisCache() {
return new RedisCacheService(); // 存在 Redis 客户端时创建
}
7. 源码调试与陷阱规避
调试步骤:
- 在 BeanFactory.getBean() 方法设置断点,观察根据 Bean 名称创建实例的过程。
- 跟踪静态工厂方法调用:在 SimpleInstantiationStrategy.instantiate() 中查看方法反射调用。
常见陷阱:
- 工厂方法单例问题:静态工厂默认返回单例,需结合 @Scope 注解控制作用域。
- 循环依赖:工厂方法中直接 new 对象可能导致 Spring 无法管理依赖(应通过容器获取 Bean)。
- 条件分支冗余:过多 if-else 应重构为策略模式或 Map 映射。
8. 性能与最佳实践
优点:
- 集中管理对象创建逻辑,降低代码冗余。
- 通过配置实现对象切换,符合开闭原则。
优化建议:
- 避免硬编码条件:将分支逻辑外置到配置文件或数据库。
- 工厂方法轻量化:不在工厂中执行业务逻辑(如 IO 操作)。
- 结合缓存机制:对频繁创建的对象使用单例或原型作用域。
欢迎讨论!