浅析 Spring 中 FactoryBean 的实现与使用
- 一、FactoryBean核心机制剖析
- 二、高级应用场景与实战
- 三、框架级应用案例解析
- 四、FactoryBean常见面试题

一、FactoryBean核心机制剖析
1. 本质与双重角色
FactoryBean是Spring容器中用于定制化对象创建的核心接口(org.springframework.beans.factory.FactoryBean
),其设计体现了两个关键特征:
- 工厂模式:通过getObject()方法动态生成目标对象
- 容器托管:FactoryBean本身作为Spring Bean被容器管理,支持依赖注入和生命周期回调
2. 接口方法详解
public interface FactoryBean<T> {T getObject() throws Exception; // 核心工厂方法Class<?> getObjectType(); // 决定自动注入的类型匹配default boolean isSingleton() { // 控制对象作用域return true;}
}
运行机制:
Spring容器初始化时,若检测到Bean实现FactoryBean接口,会通过getObject()
生成目标对象。通过&
前缀获取工厂实例本身(如getBean("&myFactory")
)
3. 源码级工作流程
参考Spring源码的Bean创建流程:
- Bean实例化:
AbstractAutowireCapableBeanFactory.createBeanInstance()
创建FactoryBean实例 - 对象生成:在
getObjectForBeanInstance()
方法中调用getObject()
生成目标对象 - 缓存处理:单例对象存入
factoryBeanObjectCache
,多例对象每次新建
关键源码片段(简化):
// AbstractBeanFactory.doGetBean()
Object beanInstance = getSingleton(beanName);
if (beanInstance instanceof FactoryBean) {return getObjectFromFactoryBean((FactoryBean<?>) beanInstance, beanName);
}
二、高级应用场景与实战
1. 多例对象动态生成
public class PrototypeToolFactory implements FactoryBean<Tool> {@Override public boolean isSingleton() {return false; // 每次请求新实例}@Overridepublic Tool getObject() {return new Tool(UUID.randomUUID().toString());}
}
应用场景:数据库连接池、线程不安全对象的按需创建
2. 手动配置代理(AOP场景)
(ProxyFactoryBean 是 Spring AOP 中用于 手动配置代理对象的核心类;而动态代理底层是基于AnnotationAwareAspectJAutoProxyCreator实现)
public class ServiceProxyFactory implements FactoryBean<Object> {private Object target;@Overridepublic Object getObject() {return Proxy.newProxyInstance(target.getClass().getClassLoader(),target.getClass().getInterfaces(),(proxy, method, args) -> {System.out.println("[Before] Method: " + method.getName());Object result = method.invoke(target, args);System.out.println("[After] Result: " + result);return result;});}
}
实现原理:Spring AOP的ProxyFactoryBean
即采用类似机制生成代理对象
3. 延迟初始化策略
public class LazyDataSourceFactory implements FactoryBean<DataSource> {private boolean initialized = false;private DataSource dataSource;@Overridepublic DataSource getObject() {if (!initialized) {initializeDataSource(); // 首次调用时初始化initialized = true;}return dataSource;}
}
优势:优化启动速度,按需加载重量级资源
三、框架级应用案例解析
1. MyBatis SqlSessionFactoryBean
核心逻辑:
- 实现
InitializingBean
确保属性设置完成后构建SqlSessionFactory
- 通过
buildSqlSessionFactory()
解析XML
配置、Mapper
映射 - 集成
Spring
事务管理
2. Spring Cloud FeignClientFactoryBean
实现机制:
- 动态生成
Feign
客户端接口代理 - 整合
Ribbon
负载均衡、Hystrix
熔断 - 通过
Targeter.target()
生成最终代理对象
3. Spring AOP ProxyFactoryBean
(ProxyFactoryBean 是 Spring AOP 中用于 手动配置代理对象的核心类;而动态代理底层是基于AnnotationAwareAspectJAutoProxyCreator实现)
<bean id="personTarget" class="com.example.PersonImpl"/>
<bean id="myAdvisor" class="com.example.MyAdvisor"/><bean id="personProxy" class="org.springframework.aop.framework.ProxyFactoryBean"><property name="target" ref="personTarget"/><property name="proxyInterfaces" value="com.example.Person"/><property name="interceptorNames"><list><value>myAdvisor</value></list></property>
</bean>
工作流程:
- 配置
Advisor
(切面)和Advice
(增强) - 通过
getObject()
生成JDK/CGLIB
代理 - 将拦截器链织入代理对象
四、FactoryBean常见面试题
1. BeanFactory 和 FactoryBean 的区别?
维度 | BeanFactory | FactoryBean |
---|---|---|
角色 | Spring 容器根接口,管理所有 Bean | 特殊 Bean,用于生成其他对象 |
获取方式 | getBean(“beanName”) 直接获取 Bean | getBean(“beanName”) 获取目标对象,&beanName 获取工厂 |
设计目标 | 提供容器基础功能(如依赖注入) | 扩展复杂对象的创建逻辑(如代理、动态配置) |
典型实现 | ApplicationContext | SqlSessionFactoryBean、ProxyFactoryBean |
2. FactoryBean 的初始化时机?
- 普通 Bean 阶段:FactoryBean 实例在 Spring 容器初始化时创建。
- 目标对象阶段:目标对象(
getObject()
生成)在首次调用getBean()
时创建,支持懒加载(@Lazy
)。 源码位置:AbstractBeanFactory.getObjectForBeanInstance()
→getObjectFromFactoryBean()
3. 如何通过 FactoryBean 实现多例对象?
-
重写方法:
isSingleton()
返回false
,每次调用getObject()
生成新实例。 -
示例:
public class PrototypeFactory implements FactoryBean<MyObject> {@Overridepublic boolean isSingleton() { return false; }@Overridepublic MyObject getObject() { return new MyObject(); } }
应用场景:线程不安全对象(如数据库连接)、动态配置对象
4. FactoryBean 在 MyBatis 中的应用?
- 案例:SqlSessionFactoryBean
- 核心流程:
- 实现
FactoryBean<SqlSessionFactory>
,在getObject()
中解析 MyBatis 配置。 - 集成 Spring 事务管理,通过
InitializingBean
确保属性初始化完成
- 实现
5. 如何获取 FactoryBean 自身实例?
- 语法:在 Bean 名称前添加
&
前缀,例如context.getBean("&myFactory")
- 原理:Spring 容器通过
BeanFactory.FACTORY_BEAN_PREFIX
标识工厂实例
6. FactoryBean 与 @Bean 注解的区别?
维度 | FactoryBean | @Bean |
---|---|---|
实现方式 | 需实现接口,编写 getObject() 逻辑 | 通过注解声明,直接返回对象实例 |
对象生成 | 动态生成(如代理、复杂初始化) | 直接实例化(简单对象) |
获取方式 | beanName 获取目标对象,&beanName 获取工厂 | 直接通过 beanName 获取实例 |
生命周期 | 支持单例/多例控制 | 默认单例,可通过 @Scope 修改 |