factorybean是spring中用于封装复杂对象创建逻辑的接口,其getobject()返回实际bean,&前缀可获取工厂本体,适用于多步初始化、代理或动态类生成等场景。

Spring 中的 FactoryBean 是专门用于封装复杂对象创建逻辑的接口,适用于那些无法通过简单构造或配置就能初始化的对象(比如需要多步初始化、依赖外部资源、涉及代理或动态生成类等场景)。
理解 FactoryBean 的核心作用
FactoryBean 不是普通 Bean,而是一个“生产 Bean 的工厂”。它让 Spring 容器在注入时,不是直接返回该 FactoryBean 实例本身,而是默认返回其 getObject() 方法的结果。你可以通过在 bean 名称前加 &(如 &myFactoryBean)来获取 FactoryBean 本体。
-
getObject():返回最终要被 Spring 管理的实际对象 -
getObjectType():声明返回对象的类型,影响依赖注入时的类型匹配 -
isSingleton():决定返回对象是否为单例(默认 true)
写一个自定义 FactoryBean 示例
比如要创建一个带连接池的 RedisTemplate,但初始化过程涉及多个步骤(设置序列化器、配置连接工厂、初始化连接池等),适合用 FactoryBean 封装:
public class RedisTemplateFactoryBean implements FactoryBean<redistemplate object>> {
private String host = "localhost";
private int port = 6379;
@Override
public RedisTemplate<string object> getObject() throws Exception {
RedisTemplate<string object> template = new RedisTemplate();
template.setConnectionFactory(createConnectionFactory());
template.setKeySerializer(new StringRedisSerializer());
template.setValueSerializer(new GenericJackson2JsonRedisSerializer());
template.afterPropertiesSet(); // 触发初始化
return template;
}
private RedisConnectionFactory createConnectionFactory() {
RedisStandaloneConfiguration config = new RedisStandaloneConfiguration(host, port);
return new LettuceConnectionFactory(config);
}
@Override
public Class extends RedisTemplate<string object>> getObjectType() {
return RedisTemplate.class;
}
@Override
public boolean isSingleton() {
return true;
}
// 提供 setter 方便配置(可通过 @Value 或 @ConfigurationProperties 注入)
public void setHost(String host) { this.host = host; }
public void setPort(int port) { this.port = port; }
}</string></string></string></redistemplate>
然后在配置类中声明:
Java开发手册规约集合,基于阿里巴巴Java开发手册(嵩山版)。 涵盖7大维度:编程规约、异常日志、单元测试、安全规约、MySQL数据库、工程结构、设计规约。 当用户需要:(1) 编写或审查Java代码 (2) 检查命名/代码规范 (3) 处理异常和日志 (4) 编写单元测试 (5) 安全编码 (6) 数据库设...
@Configuration
public class RedisConfig {
@Bean
public RedisTemplateFactoryBean redisTemplateFactoryBean() {
RedisTemplateFactoryBean factory = new RedisTemplateFactoryBean();
factory.setHost("127.0.0.1");
factory.setPort(6380);
return factory;
}
}
此时注入 RedisTemplate 时,Spring 自动调用 getObject() 并注入结果;若需注入 FactoryBean 本身,写 @Autowired @Qualifier("&redisTemplateFactoryBean") 即可。
配合 @Configuration 和泛型优化体验
为了类型安全和使用简洁,建议让 FactoryBean 实现泛型接口,并在 getObjectType() 中返回具体泛型类型(注意不能直接用 getClass().getGenericSuperclass() 获取泛型——运行时擦除,需靠子类明确返回)。
- 避免在
getObject()中抛出未检查异常,否则会中断容器启动;应捕获并包装为RuntimeException(如BeanCreationException) - 如果对象创建依赖其他 Spring Bean,可在 FactoryBean 中
@Autowired注入(Spring 4.3+ 支持构造注入,更推荐) - 注意线程安全:若
isSingleton() == false,每次getObject()都会被调用,确保内部状态不共享
替代方案对比:什么时候不用 FactoryBean?
并非所有复杂创建都需要 FactoryBean。以下情况优先考虑更轻量的方式:
- 对象构建逻辑固定、无外部依赖 → 直接用
@Bean方法(支持参数注入、条件化、生命周期回调) - 需要代理或 AOP 增强 → 用
@Scope(proxyMode = ScopedProxyMode.TARGET_CLASS)或@Primary+ 接口抽象 - 动态决定类型或实例 → 考虑
ObjectProvider<t></t>或ApplicationContext.getBean(Class<t>, ...)</t>
FactoryBean 的价值在于“对 Spring 隐藏创建细节”,让使用者像使用普通 Bean 一样使用它,同时保持高度定制能力。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










