Spring 中的 FactoryBean 与 BeanFactory:核心概念深度解析

在 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 容器处理循环依赖的核心是三级缓存机制:

  1. singletonObjects:第一级缓存,存放完全初始化好的单例 Bean
  2. earlySingletonObjects:第二级缓存,存放半初始化的 Bean
  3. 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 实现方式

总结与最佳实践

  1. 区分使用场景

    • BeanFactory:作为容器使用,管理 Bean
    • FactoryBean:需要封装复杂初始化逻辑或动态代理时使用
  2. FactoryBean 最佳实践

    • 单例 Bean 需确保线程安全
    • 实现 DisposableBean 管理资源释放
    • 使用 InitializingBean 进行初始化
    • 提供详细的日志和异常处理
    • 避免在 getObject()中执行耗时操作,或使用异步方式处理
  3. 性能优化策略

    • FactoryBean 的 getObject()可能被频繁调用,注意优化
    • 单例 Bean 应缓存创建结果
    • 考虑使用懒加载策略避免启动时的性能开销
    • 对于耗时操作,使用 AsyncFactoryBean 实现异步初始化
  4. 安全最佳实践

    • 敏感配置使用属性占位符和加密配置
    • 外部输入必须验证和清理
    • 资源必须正确关闭,避免泄漏
    • 使用构建者模式或工厂方法提高 API 安全性和可用性

理解这两个核心概念的区别,不仅有助于正确使用 Spring 框架,也能帮助我们设计出更灵活、可维护的应用架构。

参考资料

相关推荐
全栈凯哥几秒前
Java详解LeetCode 热题 100(27):LeetCode 21. 合并两个有序链表(Merge Two Sorted Lists)详解
java·算法·leetcode·链表
YuTaoShao1 分钟前
Java八股文——集合「List篇」
java·开发语言·list
PypYCCcccCc6 分钟前
支付系统架构图
java·网络·金融·系统架构
华科云商xiao徐27 分钟前
Java HttpClient实现简单网络爬虫
java·爬虫
扎瓦40 分钟前
ThreadLocal 线程变量
java·后端
JiangJiang43 分钟前
🔥 面试官:Webpack 为什么能热更新?你真讲得清吗?
前端·面试·webpack
BillKu1 小时前
Java后端检查空条件查询
java·开发语言
jackson凌1 小时前
【Java学习笔记】String类(重点)
java·笔记·学习
蒟蒻小袁1 小时前
力扣面试150题--被围绕的区域
leetcode·面试·深度优先
掘金安东尼1 小时前
字节-Trae、阿里-通义灵码、腾讯-CodeBuddy,为什么都在“卷”AI编码?
面试·llm·github