在 Spring 框架中,FactoryBean 和 BeanFactory 是两个名字相似但功能和定位完全不同的核心组件。理解这两者的区别对于掌握 Spring IoC 容器的工作原理至关重要。本文将通过代码示例、图表和实际应用场景,帮你彻底理解这两个概念。
BeanFactory:Spring IoC 容器的基础
BeanFactory 是 Spring IoC(控制反转)容器的根接口,是整个 Spring 框架的基石。它负责 Bean 的完整生命周期管理,包括创建、配置、装配和销毁。
java
public interface BeanFactory {
// 根据bean名称获取实例
Object getBean(String name) throws BeansException;
// 根据bean名称和类型获取实例
<T> T getBean(String name, Class<T> requiredType) throws BeansException;
// 根据类型获取实例
<T> T getBean(Class<T> requiredType) throws BeansException;
// 判断容器是否包含指定bean
boolean containsBean(String name);
// 判断bean是否为单例
boolean isSingleton(String name) throws NoSuchBeanDefinitionException;
// 获取bean的类型
Class<?> getType(String name) throws NoSuchBeanDefinitionException;
// 获取bean的别名
String[] getAliases(String name);
}
BeanFactory 的核心实现
在 Spring 5.x 及以上版本中,DefaultListableBeanFactory
是 BeanFactory 接口的最主要实现:
java
// 推荐的BeanFactory使用方式
DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(factory);
reader.loadBeanDefinitions(new ClassPathResource("applicationContext.xml"));
// 获取Bean
UserService userService = factory.getBean("userService", UserService.class);
注意:早期版本中常用的 XmlBeanFactory 已在 Spring 3.1 版本被弃用,并在 Spring 5.0 中完全移除。
BeanFactory 的生命周期管理职责
BeanFactory 不仅负责创建 Bean,还管理 Bean 的完整生命周期:
java
public class LifecycleDemoBean implements InitializingBean, DisposableBean {
private static final Logger logger = LoggerFactory.getLogger(LifecycleDemoBean.class);
// 构造函数
public LifecycleDemoBean() {
logger.info("1. Bean实例化阶段:构造函数执行");
}
// 属性注入
public void setProperty(String property) {
logger.info("2. 属性设置阶段:setProperty方法执行");
}
// InitializingBean接口方法
@Override
public void afterPropertiesSet() throws Exception {
logger.info("3. 初始化阶段:afterPropertiesSet方法执行");
}
// 自定义初始化方法
public void customInit() {
logger.info("4. 初始化阶段:自定义init方法执行");
}
// 业务方法
public void businessMethod() {
logger.info("5. 使用阶段:业务方法执行");
}
// DisposableBean接口方法
@Override
public void destroy() throws Exception {
logger.info("6. 销毁阶段:destroy方法执行");
}
// 自定义销毁方法
public void customDestroy() {
logger.info("7. 销毁阶段:自定义destroy方法执行");
}
}
配置方式:
xml
<bean id="lifecycleDemo" class="com.example.LifecycleDemoBean"
init-method="customInit" destroy-method="customDestroy">
<property name="property" value="测试值"/>
</bean>
BeanFactoryPostProcessor:容器扩展机制
BeanFactory 提供了强大的扩展点,其中最重要的是 BeanFactoryPostProcessor,它允许在容器实例化 Bean 之前修改 Bean 定义:
java
public class CustomBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
private static final Logger logger = LoggerFactory.getLogger(CustomBeanFactoryPostProcessor.class);
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
logger.info("执行BeanFactoryPostProcessor,当前已加载的Bean定义数量: {}",
beanFactory.getBeanDefinitionCount());
// 修改已存在的Bean定义
if (beanFactory.containsBeanDefinition("dataSource")) {
BeanDefinition bd = beanFactory.getBeanDefinition("dataSource");
PropertyValue pv = bd.getPropertyValues().getPropertyValue("url");
if (pv != null) {
logger.info("修改dataSource的URL属性");
bd.getPropertyValues().addPropertyValue("url", "jdbc:mysql://prod-server:3306/app");
}
}
}
}
使用方式:
java
@Configuration
public class AppConfig {
@Bean
public static CustomBeanFactoryPostProcessor customBeanFactoryPostProcessor() {
return new CustomBeanFactoryPostProcessor();
}
}
ApplicationContext:BeanFactory 的强大扩展
ApplicationContext 是 BeanFactory 的子接口,提供了更多企业级功能:
java
// ApplicationContext的核心增强功能
public interface ApplicationContext extends BeanFactory,
MessageSource, // 国际化消息支持
ApplicationEventPublisher, // 事件发布功能
ResourcePatternResolver { // 资源加载能力
// 获取应用ID
String getId();
// 获取应用名称
String getApplicationName();
// 获取显示名称
String getDisplayName();
// 获取启动时间
long getStartupDate();
// 获取父上下文
ApplicationContext getParent();
}
使用示例:
java
// 基于类路径的XML配置
ApplicationContext context =
new ClassPathXmlApplicationContext("applicationContext.xml");
// 基于文件系统的XML配置
ApplicationContext context =
new FileSystemXmlApplicationContext("C:/config/applicationContext.xml");
// Web应用中的配置
WebApplicationContext context =
WebApplicationContextUtils.getWebApplicationContext(servletContext);
// 使用国际化消息
String message = context.getMessage("message.key", null, Locale.CHINA);
// 发布自定义事件
context.publishEvent(new CustomEvent(this, "数据已更新"));
Java 配置方式
从 Spring 3.0 开始,注解配置成为主流方式:
java
@Configuration
@ComponentScan("com.example")
public class AppConfig {
@Bean
public UserService userService() {
return new UserServiceImpl();
}
@Bean
public DataSource dataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
dataSource.setUrl("${db.url}");
dataSource.setUsername("${db.username}");
dataSource.setPassword("${db.password}");
return dataSource;
}
}
// 使用Java配置
ApplicationContext context =
new AnnotationConfigApplicationContext(AppConfig.class);
FactoryBean:专门创建复杂对象的工厂接口
FactoryBean 是一个特殊的 Bean,它本身是一个工厂,用于创建和管理其他 Bean 实例。当需要创建过程复杂的 Bean 对象时,FactoryBean 提供了优雅的封装方案。
在 Spring 5.x 中,FactoryBean 接口定义如下:
java
public interface FactoryBean<T> {
// 创建对象实例
T getObject() throws Exception;
// 返回创建对象的类型
Class<?> getObjectType();
// 创建的对象是否为单例(从Spring 5.0开始提供默认实现)
default boolean isSingleton() {
return true;
}
}
自定义 FactoryBean 实现
下面是一个创建数据库连接的 FactoryBean 完整实现:
java
public class ConnectionFactoryBean implements FactoryBean<Connection>, DisposableBean {
private static final Logger logger = LoggerFactory.getLogger(ConnectionFactoryBean.class);
private static final String VALIDATION_QUERY = "SELECT 1";
private String url;
private String username;
private String password;
private Connection connection;
// setter方法
public void setUrl(String url) { this.url = url; }
public void setUsername(String username) { this.username = username; }
public void setPassword(String password) { this.password = password; }
@Override
public Connection getObject() throws Exception {
if (connection == null) {
logger.info("创建数据库连接: {}", url);
try {
// 创建数据库连接
connection = DriverManager.getConnection(url, username, password);
// 验证连接有效性
try (Statement stmt = connection.createStatement()) {
stmt.executeQuery(VALIDATION_QUERY);
}
} catch (SQLException e) {
logger.error("数据库连接创建失败", e);
throw new BeanCreationException("数据库连接创建失败", e);
}
}
return connection;
}
@Override
public Class<?> getObjectType() {
return Connection.class;
}
@Override
public boolean isSingleton() {
return true; // 单例模式,复用连接
}
@Override
public void destroy() throws Exception {
// 销毁资源
if (connection != null && !connection.isClosed()) {
logger.info("关闭数据库连接");
connection.close();
}
}
}
安全的配置方式:
xml
<bean id="dbConnection" class="com.example.ConnectionFactoryBean">
<property name="url" value="${db.url}"/>
<property name="username" value="${db.username}"/>
<property name="password" value="${db.password}"/>
</bean>
<!-- 属性占位符配置 -->
<context:property-placeholder location="classpath:db.properties"/>
使用方式:
java
// 获取FactoryBean创建的Connection对象
Connection conn = (Connection) context.getBean("dbConnection");
// 获取FactoryBean本身
ConnectionFactoryBean factoryBean =
(ConnectionFactoryBean) context.getBean("&dbConnection");
FactoryBean 的高级应用场景
动态代理对象创建
FactoryBean 最强大的应用场景之一是创建动态代理对象。下面通过构建者模式实现一个灵活的服务代理工厂:
java
public class ServiceProxyFactoryBean<T> implements FactoryBean<T> {
private static final Logger logger = LoggerFactory.getLogger(ServiceProxyFactoryBean.class);
private Class<T> serviceInterface;
private Object target;
private List<MethodInterceptor> interceptors = new ArrayList<>();
// 私有构造函数,通过Builder创建实例
private ServiceProxyFactoryBean() {}
public void setServiceInterface(Class<T> serviceInterface) {
this.serviceInterface = serviceInterface;
}
public void setTarget(Object target) {
this.target = target;
}
public void setInterceptors(List<MethodInterceptor> interceptors) {
this.interceptors = interceptors;
}
@SuppressWarnings("unchecked")
@Override
public T getObject() throws Exception {
if (serviceInterface == null) {
throw new IllegalArgumentException("Property 'serviceInterface' is required");
}
if (target == null) {
throw new IllegalArgumentException("Property 'target' is required");
}
logger.info("为接口 {} 创建代理", serviceInterface.getName());
ProxyFactory proxyFactory = new ProxyFactory();
proxyFactory.setTarget(target);
proxyFactory.setInterfaces(serviceInterface);
// 添加通用的性能监控和日志拦截器
proxyFactory.addAdvice(new PerformanceMonitorInterceptor());
proxyFactory.addAdvice(new CustomLogInterceptor());
// 添加自定义拦截器
for (MethodInterceptor interceptor : interceptors) {
proxyFactory.addAdvice(interceptor);
}
return (T) proxyFactory.getProxy();
}
@Override
public Class<?> getObjectType() {
return serviceInterface;
}
// 构建者模式
public static class Builder<T> {
private final ServiceProxyFactoryBean<T> factoryBean;
public Builder() {
this.factoryBean = new ServiceProxyFactoryBean<>();
this.factoryBean.interceptors = new ArrayList<>();
}
public Builder<T> serviceInterface(Class<T> serviceInterface) {
this.factoryBean.serviceInterface = serviceInterface;
return this;
}
public Builder<T> target(Object target) {
this.factoryBean.target = target;
return this;
}
public Builder<T> addInterceptor(MethodInterceptor interceptor) {
this.factoryBean.interceptors.add(interceptor);
return this;
}
public ServiceProxyFactoryBean<T> build() {
return this.factoryBean;
}
}
public static <T> Builder<T> builder() {
return new Builder<>();
}
// 性能监控拦截器
private static class PerformanceMonitorInterceptor implements MethodInterceptor {
private static final Logger perfLogger = LoggerFactory.getLogger("performance");
@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
long startTime = System.currentTimeMillis();
try {
return invocation.proceed();
} finally {
long endTime = System.currentTimeMillis();
perfLogger.info("方法 {}.{} 执行耗时: {}ms",
invocation.getMethod().getDeclaringClass().getSimpleName(),
invocation.getMethod().getName(),
(endTime - startTime));
}
}
}
// 日志拦截器
private static class CustomLogInterceptor implements MethodInterceptor {
private static final Logger logger = LoggerFactory.getLogger(CustomLogInterceptor.class);
@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
logger.debug("调用方法: {}.{}",
invocation.getMethod().getDeclaringClass().getSimpleName(),
invocation.getMethod().getName());
try {
Object result = invocation.proceed();
logger.debug("方法调用成功");
return result;
} catch (Throwable t) {
logger.error("方法调用失败", t);
throw t;
}
}
}
}
使用构建者模式的示例:
java
@Configuration
public class ProxyConfig {
@Bean
public UserService userServiceTarget() {
return new UserServiceImpl();
}
@Bean
public ServiceProxyFactoryBean<UserService> userService() {
return ServiceProxyFactoryBean.<UserService>builder()
.serviceInterface(UserService.class)
.target(userServiceTarget())
.addInterceptor(new TransactionInterceptor())
.build();
}
}
异步 FactoryBean 实现
利用 CompletableFuture 实现异步初始化的 FactoryBean,适用于耗时初始化场景:
java
public class AsyncFactoryBean<T> implements FactoryBean<T>, InitializingBean {
private static final Logger logger = LoggerFactory.getLogger(AsyncFactoryBean.class);
private final Supplier<T> objectSupplier;
private final Class<T> objectType;
private CompletableFuture<T> futureInstance;
private long timeoutSeconds = 5;
public AsyncFactoryBean(Supplier<T> objectSupplier, Class<T> objectType) {
this.objectSupplier = objectSupplier;
this.objectType = objectType;
}
public void setTimeoutSeconds(long timeoutSeconds) {
this.timeoutSeconds = timeoutSeconds;
}
@Override
public void afterPropertiesSet() {
logger.info("启动异步初始化: {}", objectType.getName());
this.futureInstance = CompletableFuture.supplyAsync(() -> {
try {
logger.info("异步创建对象: {}", objectType.getName());
return objectSupplier.get();
} catch (Exception e) {
logger.error("异步对象创建失败", e);
throw new CompletionException(e);
}
});
}
@Override
public T getObject() throws Exception {
try {
logger.debug("等待异步对象完成,超时时间: {}秒", timeoutSeconds);
return futureInstance.get(timeoutSeconds, TimeUnit.SECONDS);
} catch (TimeoutException e) {
logger.error("异步创建对象超时", e);
throw new BeanCreationException("异步创建Bean超时: " + objectType.getName(), e);
} catch (ExecutionException e) {
logger.error("异步创建对象失败", e);
throw new BeanCreationException("异步创建Bean失败: " + objectType.getName(), e.getCause());
}
}
@Override
public Class<?> getObjectType() {
return objectType;
}
}
使用示例:
java
@Configuration
public class AsyncConfig {
@Bean
public AsyncFactoryBean<ExpensiveService> expensiveService() {
AsyncFactoryBean<ExpensiveService> factoryBean =
new AsyncFactoryBean<>(() -> {
// 模拟耗时初始化
try {
Thread.sleep(3000);
return new ExpensiveServiceImpl();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw new RuntimeException("初始化中断", e);
}
}, ExpensiveService.class);
factoryBean.setTimeoutSeconds(10);
return factoryBean;
}
}
事务管理与 FactoryBean
FactoryBean 在 Spring 事务管理中也扮演重要角色,例如TransactionProxyFactoryBean
用于创建事务代理:
java
@Configuration
public class TransactionConfig {
@Bean
public PlatformTransactionManager transactionManager(DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
@Bean
public TransactionProxyFactoryBean userServiceProxy(
PlatformTransactionManager transactionManager) {
TransactionProxyFactoryBean factoryBean = new TransactionProxyFactoryBean();
factoryBean.setTarget(userServiceTarget());
factoryBean.setTransactionManager(transactionManager);
// 事务属性配置
Properties transactionAttributes = new Properties();
transactionAttributes.setProperty("save*", "PROPAGATION_REQUIRED,-Exception");
transactionAttributes.setProperty("update*", "PROPAGATION_REQUIRED,-Exception");
transactionAttributes.setProperty("delete*", "PROPAGATION_REQUIRED,-Exception");
transactionAttributes.setProperty("get*", "PROPAGATION_SUPPORTS,readOnly");
transactionAttributes.setProperty("find*", "PROPAGATION_SUPPORTS,readOnly");
factoryBean.setTransactionAttributes(transactionAttributes);
return factoryBean;
}
@Bean
public UserService userServiceTarget() {
return new UserServiceImpl();
}
}
在现代 Spring 中,通常使用@Transactional
注解替代上述配置,但了解 FactoryBean 的事务代理原理仍然重要。
FactoryBean 在循环依赖场景中的处理
Spring 容器处理循环依赖时,FactoryBean 需要特殊处理:
java
// 假设存在循环依赖:ServiceA → ServiceB → ServiceA
@Configuration
public class CircularDependencyConfig {
@Bean
public ServiceA serviceA(ObjectProvider<ServiceB> serviceBProvider) {
// 使用ObjectProvider延迟注入,避免循环依赖问题
return new ServiceA(() -> serviceBProvider.getObject());
}
@Bean
public ServiceFactoryBean serviceB() {
ServiceFactoryBean factoryBean = new ServiceFactoryBean();
return factoryBean;
}
public static class ServiceFactoryBean implements FactoryBean<ServiceB>,
BeanFactoryAware {
private BeanFactory beanFactory;
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
this.beanFactory = beanFactory;
}
@Override
public ServiceB getObject() throws Exception {
ServiceB service = new ServiceB();
// 延迟注入ServiceA,避免循环依赖问题
service.setServiceA((ServiceA) beanFactory.getBean("serviceA"));
return service;
}
@Override
public Class<?> getObjectType() {
return ServiceB.class;
}
}
}
Spring 容器处理循环依赖的核心是三级缓存机制:
- singletonObjects:第一级缓存,存放完全初始化好的单例 Bean
- earlySingletonObjects:第二级缓存,存放半初始化的 Bean
- singletonFactories:第三级缓存,存放 Bean 工厂对象
当处理 FactoryBean 循环依赖时,Spring 需要处理两层缓存问题:FactoryBean 本身和它创建的对象。在这种情况下,推荐使用 ObjectProvider 或延迟注入方式解决循环依赖问题,而不是构造器注入。
MyBatis 与 Spring 集成:FactoryBean 实战
MyBatis-Spring 框架中的 SqlSessionFactoryBean 是 FactoryBean 的典型应用:
java
public class SqlSessionFactoryBean implements FactoryBean<SqlSessionFactory>,
InitializingBean, ApplicationListener<ContextRefreshedEvent> {
private static final Logger logger = LoggerFactory.getLogger(SqlSessionFactoryBean.class);
// 提取常量
private static final String DEFAULT_ENV_ID = "default";
private static final String MAPPER_LOCATION_PATTERN = "classpath:mapper/*.xml";
private Resource configLocation;
private Resource[] mapperLocations;
private DataSource dataSource;
private SqlSessionFactory sqlSessionFactory;
// setter方法省略...
@Override
public void afterPropertiesSet() throws Exception {
if (dataSource == null) {
throw new IllegalArgumentException("Property 'dataSource' is required");
}
// 创建SqlSessionFactory
try {
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
// 使用Optional优雅处理可能为null的configLocation
Optional.ofNullable(configLocation)
.ifPresentOrElse(
// 有配置文件时
config -> {
logger.info("加载MyBatis配置文件: {}", config);
try (InputStream inputStream = config.getInputStream()) {
this.sqlSessionFactory = builder.build(inputStream);
} catch (IOException e) {
throw new BeanInitializationException("Failed to load MyBatis config", e);
}
},
// 无配置文件时创建默认配置
() -> {
Configuration configuration = new Configuration();
// 设置数据源
configuration.setEnvironment(new Environment(DEFAULT_ENV_ID,
new SpringManagedTransactionFactory(), dataSource));
// 构建SqlSessionFactory
this.sqlSessionFactory = new DefaultSqlSessionFactory(configuration);
// 处理Mapper文件
try {
Resource[] resources = Optional.ofNullable(mapperLocations)
.orElseGet(() -> {
try {
return new PathMatchingResourcePatternResolver()
.getResources(MAPPER_LOCATION_PATTERN);
} catch (IOException e) {
logger.warn("无法加载默认Mapper位置", e);
return new Resource[0];
}
});
processMapperLocations(configuration, resources);
} catch (IOException e) {
throw new BeanInitializationException("Failed to process mapper resources", e);
}
}
);
} catch (Exception e) {
logger.error("初始化SqlSessionFactory失败", e);
throw new BeanCreationException("初始化SqlSessionFactory失败", e);
}
}
private void processMapperLocations(Configuration configuration, Resource[] mapperLocations)
throws IOException {
for (Resource mapperLocation : mapperLocations) {
if (mapperLocation == null) {
continue;
}
try (InputStream inputStream = mapperLocation.getInputStream()) {
XMLMapperBuilder xmlMapperBuilder = new XMLMapperBuilder(
inputStream,
configuration,
mapperLocation.toString(),
configuration.getSqlFragments());
xmlMapperBuilder.parse();
} catch (Exception e) {
logger.error("解析Mapper文件失败: " + mapperLocation, e);
throw new BeanInitializationException("Failed to parse mapping resource", e);
}
}
}
@Override
public SqlSessionFactory getObject() throws Exception {
if (this.sqlSessionFactory == null) {
afterPropertiesSet();
}
return this.sqlSessionFactory;
}
@Override
public Class<?> getObjectType() {
return SqlSessionFactory.class;
}
@Override
public void onApplicationEvent(ContextRefreshedEvent event) {
// 应用上下文刷新后可执行的逻辑
}
}
Spring Boot 环境下的配置
在 Spring Boot 中,MyBatis 的集成更加简化:
java
@Configuration
@MapperScan("com.example.mapper")
public class MyBatisConfig {
@Bean
public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception {
SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();
factoryBean.setDataSource(dataSource);
factoryBean.setMapperLocations(
new PathMatchingResourcePatternResolver().getResources("classpath:mapper/*.xml"));
return factoryBean.getObject();
}
@Bean
public SqlSessionTemplate sqlSessionTemplate(SqlSessionFactory sqlSessionFactory) {
return new SqlSessionTemplate(sqlSessionFactory);
}
}
现代 Spring 中的 Kotlin 支持
Spring 5.x 开始全面支持 Kotlin,FactoryBean 在 Kotlin 中的实现更加简洁:
kotlin
// Kotlin实现的FactoryBean
class KotlinServiceFactoryBean : FactoryBean<UserService> {
override fun getObject(): UserService {
return object : UserService {
override fun findUserById(id: Long): User {
// 实现逻辑
return User(id, "用户 $id")
}
override fun saveUser(user: User): Boolean {
// 实现逻辑
return true
}
}
}
override fun getObjectType(): Class<*> = UserService::class.java
// 使用默认实现
// override fun isSingleton(): Boolean = true
}
// 在配置类中使用
@Configuration
class KotlinConfig {
@Bean
fun userService(): FactoryBean<UserService> = KotlinServiceFactoryBean()
// 使用Kotlin DSL创建FactoryBean
@Bean
fun dynamicService(): FactoryBean<DynamicService> = factoryBean {
DynamicServiceImpl().apply {
setProperty("动态生成的服务")
}
}
// 扩展函数简化FactoryBean创建
inline fun <reified T> factoryBean(crossinline function: () -> T): FactoryBean<T> {
return object : FactoryBean<T> {
override fun getObject(): T = function()
override fun getObjectType(): Class<*> = T::class.java
}
}
}
FactoryBean 与 BeanFactory 的工作流程
BeanFactory 工作流程

FactoryBean 工作流程

FactoryBean 在高并发环境下的处理
FactoryBean 在高并发场景下需要特别注意线程安全问题:
java
public class ThreadSafeFactoryBean<T> implements FactoryBean<T> {
private final Class<T> beanClass;
private final AtomicReference<T> singletonInstance = new AtomicReference<>();
private static final Logger logger = LoggerFactory.getLogger(ThreadSafeFactoryBean.class);
public ThreadSafeFactoryBean(Class<T> beanClass) {
this.beanClass = beanClass;
}
@Override
public T getObject() throws Exception {
// 单例模式下的双重检查锁定
if (isSingleton()) {
T instance = singletonInstance.get();
if (instance == null) {
synchronized (this) {
instance = singletonInstance.get();
if (instance == null) {
logger.debug("创建{}的新实例", beanClass.getName());
instance = createInstance();
singletonInstance.set(instance);
}
}
}
return instance;
} else {
// 原型模式每次创建新实例
logger.debug("创建{}的原型实例", beanClass.getName());
return createInstance();
}
}
protected T createInstance() throws Exception {
try {
// 创建实例的具体逻辑
return beanClass.getDeclaredConstructor().newInstance();
} catch (Exception e) {
logger.error("创建{}实例失败", beanClass.getName(), e);
throw e;
}
}
@Override
public Class<?> getObjectType() {
return beanClass;
}
}
单元测试 FactoryBean
FactoryBean 的测试示例:
java
@RunWith(SpringRunner.class)
@ContextConfiguration(classes = TestConfig.class)
public class ConnectionFactoryBeanTest {
@Autowired
private ApplicationContext context;
@Test
public void testConnectionFactoryBean() throws Exception {
// 测试获取创建的对象
Connection connection = (Connection) context.getBean("dbConnection");
assertNotNull("连接不应为空", connection);
assertFalse("连接应该是打开的", connection.isClosed());
// 执行简单查询验证连接可用
try (Statement stmt = connection.createStatement();
ResultSet rs = stmt.executeQuery("SELECT 1")) {
assertTrue(rs.next());
assertEquals(1, rs.getInt(1));
}
// 测试获取FactoryBean本身
ConnectionFactoryBean factoryBean =
(ConnectionFactoryBean) context.getBean("&dbConnection");
assertNotNull("FactoryBean不应为空", factoryBean);
assertEquals(Connection.class, factoryBean.getObjectType());
}
@Configuration
static class TestConfig {
@Bean
public ConnectionFactoryBean dbConnection() {
ConnectionFactoryBean factory = new ConnectionFactoryBean();
factory.setUrl("jdbc:h2:mem:test;DB_CLOSE_DELAY=-1");
factory.setUsername("sa");
factory.setPassword("");
return factory;
}
}
}
两者关系的详细对比
特性 | BeanFactory | FactoryBean |
---|---|---|
本质 | 容器接口,IoC 的基础设施 | 工厂 Bean 接口,创建复杂对象 |
作用 | 管理所有 Bean 的创建、装配和销毁 | 封装复杂对象的创建逻辑 |
使用者 | Spring 框架内部,应用上下文实现 | 应用开发者,用于定制 Bean 创建过程 |
扩展方式 | 通过后处理器扩展(BeanPostProcessor) | 通过实现接口定制创建过程 |
生命周期管理 | 负责所有 Bean 的完整生命周期 | 通常实现 InitializingBean/DisposableBean |
访问方式 | 容器直接使用 | 使用 bean id 获取创建的对象,&前缀获取工厂本身 |
线程安全 | 由框架保证 | 需开发者自行处理 |
适用场景 | Spring 框架的基础设施 | 第三方库集成、动态代理、复杂初始化逻辑 |
Spring Boot | 自动配置的基础 | 用于自定义 starter 组件创建 |
循环依赖处理 | 通过三级缓存处理 | 需特别注意延迟注入或 setter 注入 |
Kotlin 支持 | 完全支持 | 提供更简洁的 DSL 实现方式 |
总结与最佳实践
-
区分使用场景
- BeanFactory:作为容器使用,管理 Bean
- FactoryBean:需要封装复杂初始化逻辑或动态代理时使用
-
FactoryBean 最佳实践
- 单例 Bean 需确保线程安全
- 实现 DisposableBean 管理资源释放
- 使用 InitializingBean 进行初始化
- 提供详细的日志和异常处理
- 避免在 getObject()中执行耗时操作,或使用异步方式处理
-
性能优化策略
- FactoryBean 的 getObject()可能被频繁调用,注意优化
- 单例 Bean 应缓存创建结果
- 考虑使用懒加载策略避免启动时的性能开销
- 对于耗时操作,使用 AsyncFactoryBean 实现异步初始化
-
安全最佳实践
- 敏感配置使用属性占位符和加密配置
- 外部输入必须验证和清理
- 资源必须正确关闭,避免泄漏
- 使用构建者模式或工厂方法提高 API 安全性和可用性
理解这两个核心概念的区别,不仅有助于正确使用 Spring 框架,也能帮助我们设计出更灵活、可维护的应用架构。