三亩地 三亩地SAN MU DI · CODE DIARY
ARTICLE DETAIL

日记详情

真实记录编程学习的某一天,欢迎挑你感兴趣的翻一翻。

Spring FactoryBean原理与应用实战

Spring FactoryBean原理与应用实战

1. Spring FactoryBean深度解析:从原理到实战

在Spring框架中,FactoryBean是一个容易被忽视但极其重要的接口。我第一次真正理解它的价值是在一个需要集成第三方库的项目中——当时需要创建一个复杂的RPC客户端实例,而FactoryBean完美解决了对象创建流程定制化的问题。与普通Bean不同,FactoryBean是生产Bean的工厂,这种间接性为Spring容器提供了更灵活的对象创建方式。

2. FactoryBean核心机制剖析

2.1 接口定义与生命周期

FactoryBean接口定义非常简单却强大:

public interface FactoryBean<T> { T getObject() throws Exception; Class<?> getObjectType(); boolean isSingleton(); }

这三个方法构成了FactoryBean的核心契约:

  • getObject():返回工厂创建的对象实例
  • getObjectType():声明工厂生产对象的类型
  • isSingleton():控制对象是否为单例

在Spring容器初始化时,FactoryBean会经历特殊的处理流程:

  1. 容器识别到Bean定义实现了FactoryBean接口
  2. 调用getObjectType()确定实际注入类型
  3. 根据isSingleton()决定是否缓存实例
  4. 在依赖注入时调用getObject()获取最终对象

2.2 与普通Bean的差异对比

通过对比表格可以清晰看出区别:

特性普通BeanFactoryBean
容器中存储的对象Bean实例本身FactoryBean实例
获取实际对象的方式直接获取通过&前缀或类型转换
创建逻辑复杂度简单实例化可包含复杂构建逻辑
适用场景标准对象创建需要定制的对象创建

3. 典型应用场景与实战

3.1 MyBatis-Spring集成原理

MyBatis的SqlSessionFactoryBean是FactoryBean的经典实现:

public class SqlSessionFactoryBean implements FactoryBean<SqlSessionFactory> { private DataSource dataSource; private Configuration configuration; @Override public SqlSessionFactory getObject() throws Exception { // 构建复杂的MyBatis工厂对象 SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder(); return builder.build(configuration); } // 其他方法实现... }

这种设计使得:

  1. 复杂的SqlSessionFactory构建过程对Spring透明
  2. 可以在XML或Java配置中灵活设置属性
  3. 延迟到真正需要时才创建重量级对象

3.2 动态代理创建场景

实现AOP动态代理的FactoryBean示例:

public class ServiceProxyFactoryBean implements FactoryBean<Object> { private Object target; private Class<?> serviceInterface; @Override public Object getObject() { return Proxy.newProxyInstance( getClass().getClassLoader(), new Class<?>[] {serviceInterface}, new InvocationHandler() { // 代理逻辑实现 } ); } // 其他方法实现... }

4. 高级使用技巧与陷阱规避

4.1 对象获取的正确姿势

从容器获取FactoryBean生产的对象时,常见的两种方式:

  1. 按实际类型注入(推荐):
@Autowired private Product actualProduct;
  1. 需要获取FactoryBean本身时(使用&前缀):
@Autowired @Qualifier("&productFactory") private FactoryBean<Product> factoryBean;

4.2 循环引用问题解决方案

当FactoryBean之间存在相互依赖时,可以采用以下模式:

public class FactoryBeanA implements FactoryBean<A>, SmartFactoryBean { @Autowired private FactoryBeanB factoryBeanB; @Override public boolean isEagerInit() { return true; // 声明需要提前初始化 } // 其他实现... }

关键点:

  • 实现SmartFactoryBean接口
  • 通过isEagerInit()控制初始化顺序
  • 结合@DependsOn注解明确依赖关系

5. 性能优化实践

5.1 延迟初始化策略

对于资源消耗大的对象,可以实现SmartFactoryBean

public class HeavyResourceFactoryBean implements SmartFactoryBean<HeavyResource> { @Override public boolean isEagerInit() { return false; // 延迟初始化 } @Override public HeavyResource getObject() { // 重量级资源初始化逻辑 } // 其他实现... }

5.2 原型模式下的对象池

结合原型作用域实现轻量级对象池:

@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) public class ConnectionPoolFactoryBean implements FactoryBean<Connection> { private final BlockingQueue<Connection> pool = new LinkedBlockingQueue<>(10); @PostConstruct public void initPool() { // 初始化连接池 } @Override public Connection getObject() { return pool.take(); // 从池中获取连接 } @PreDestroy public void destroyPool() { // 清理资源 } // 其他实现... }

6. 与Spring Boot的深度集成

6.1 条件化FactoryBean实现

结合@Conditional实现智能创建:

public class ConditionalServiceFactoryBean implements FactoryBean<Service>, InitializingBean { private Environment env; private Service service; @Override public void afterPropertiesSet() { if (env.acceptsProfiles("cloud")) { this.service = new CloudService(); } else { this.service = new DefaultService(); } } @Override public Service getObject() { return this.service; } // 其他实现... }

6.2 自动配置中的FactoryBean

在Spring Boot自动配置中典型应用:

@AutoConfiguration @ConditionalOnClass(ThirdParty.class) public class ThirdPartyAutoConfiguration { @Bean @ConditionalOnMissingBean public ThirdPartyFactoryBean thirdParty() { return new ThirdPartyFactoryBean(); } }

7. 源码级深度解析

7.1 Spring容器处理流程

AbstractBeanFactory中关键代码片段:

protected Object getObjectForBeanInstance( Object beanInstance, String name, String beanName, RootBeanDefinition mbd) { // 如果请求的是FactoryBean本身(以&开头) if (BeanFactoryUtils.isFactoryDereference(name)) { return beanInstance; } // 处理普通FactoryBean情况 if (beanInstance instanceof FactoryBean) { return getObjectFromFactoryBean((FactoryBean<?>) beanInstance, name, beanName); } // 其他处理... }

7.2 类型系统集成原理

Spring在类型处理时的特殊逻辑:

  1. 通过getObjectType()确定注入点匹配类型
  2. 使用ResolvableType处理泛型信息
  3. DefaultListableBeanFactory中维护特殊类型映射

8. 常见问题排查指南

8.1 典型异常场景

异常现象可能原因解决方案
注入类型不匹配getObjectType()返回null明确实现getObjectType()方法
循环依赖初始化失败FactoryBean相互引用使用SmartFactoryBean接口
预期单例但获取到多个实例isSingleton()实现错误检查方法返回值
&前缀获取不到FactoryBean实例错误的Bean名称解析确保使用规范命名方式

8.2 调试技巧

  1. getObject()方法中添加断点
  2. 使用BeanFactory.getType()检查类型推断
  3. 通过BeanDefinitionRegistry检查注册的Bean定义
  4. 开启Spring调试日志观察初始化顺序

9. 扩展应用:自定义FactoryBean

9.1 动态数据源切换实现

public class RoutingDataSourceFactoryBean implements FactoryBean<DataSource>, ApplicationContextAware { private ApplicationContext context; private Map<String, DataSource> dataSources; @Override public DataSource getObject() { RoutingDataSource ds = new RoutingDataSource(); ds.setTargetDataSources(dataSources); ds.setDefaultTargetDataSource( context.getBean("primaryDataSource", DataSource.class)); return ds; } @Override public void setApplicationContext(ApplicationContext ctx) { this.context = ctx; this.dataSources = ctx.getBeansOfType(DataSource.class) .entrySet().stream() .filter(e -> !e.getKey().equals("primaryDataSource")) .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); } // 其他实现... }

9.2 响应式编程集成

public class ReactiveClientFactoryBean implements FactoryBean<ReactiveClient>, InitializingBean { private WebClient webClient; private ReactiveClient client; @Override public void afterPropertiesSet() { this.client = new DefaultReactiveClient(webClient); } @Override public ReactiveClient getObject() { return this.client; } // 其他实现... }

在Spring生态中,FactoryBean的这种间接创建模式为框架集成提供了标准化的接入点。从MyBatis到各种中间件客户端,几乎所有的复杂对象创建场景都能看到它的身影。理解其工作原理后,开发者可以更自如地扩展Spring容器的能力边界

← 返回列表