商城首页欢迎来到中国正版软件门户

您的位置: 首页 > 文章列表 > 编程开发 > FactoryBean使用及真实应用场景分享

FactoryBean使用及真实应用场景分享

  发布于2026-05-31 阅读(0)

扫一扫,手机访问

一、FactoryBean是什么?

FactoryBean 这个接口,说白了就是 Spring 给咱们预留的一个“自定义对象工厂”的钩子。你实现它之后,把它丢进 Spring 容器,它不光自己会变成 bean,还能捎带手把它要创建的 bean 也一并注册进去。本质上和设计模式里的工厂模式没啥两样——区别只在于一个是 Spring 容器帮你管,另一个得你自个儿手动折腾。

接口里就三个方法,核心逻辑全在这儿了:

public interface FactoryBean {

    String OBJECT_TYPE_ATTRIBUTE = "factoryBeanObjectType";

    @Nullable
    T getObject() throws Exception;

    @Nullable
    Class getObjectType();

    default boolean isSingleton() {
        return true;
    }
}

getObject() 返回你要创建的 bean 实例;getObjectType() 告诉别人这个 bean 的类型是啥;isSingleton() 决定要不要缓存为单例,默认 true。简单明了。

二、使用

在实际场景里,FactoryBean 很少单独出现,往往是和 Spring 提供的其他接口(比如 InitializingBean)搭着用。

1. 造个 bean 和它的 Builder

先准备一个普通的 POJO 和一个 Builder,方便后续组装:

@Data
public class Customize {
    private String id;
    private String name;
    private int age;
    private String address;
    private String phone;
}

public class CustomizeBuilder {
    private Customize customize;

    public CustomizeBuilder builder() {
        customize = new Customize();
        return this;
    }
    // ... 各种 setter 方法
    public Customize build() {
        return customize;
    }
}

2. 创建 FactoryBean 实例

写一个 CustomizeFactoryBean,同时实现 FactoryBeanInitializingBean。后者会在所有属性注入完成后自动调用 afterPropertiesSet(),我们正好在这里把 bean 初始化好。

@Component
public class CustomizeFactoryBean implements FactoryBean, InitializingBean {

    private Customize customize;

    @Override
    public Customize getObject() throws Exception {
        return customize;
    }

    @Override
    public Class getObjectType() {
        return Customize.class;
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        if (customize == null) {
            customize = new CustomizeBuilder().builder()
                    .id("1")
                    .name("sun")
                    .age(18)
                    .address("beijing")
                    .phone("123456789")
                    .build();
        }
    }
}

接着写个测试类验证一下:

@SpringBootTest
class SpringBeanApplicationTests {
    @Autowired
    private Customize customize;
    @Autowired
    private CustomizeFactoryBean customizeFactoryBean;

    @Test
    public void contextLoads() throws Exception {
        System.out.println(customizeFactoryBean);
        System.out.println(customizeFactoryBean.getObject());
        System.out.println(customize);
    }
}

输出结果:

com.agp.springbean.factorybean.CustomizeFactoryBean@5a592c70

Customize(id=1, name=sun, age=18, address=beijing, phone=123456789)

Customize(id=1, name=sun, age=18, address=beijing, phone=123456789)

跑一下就能看出,@Autowired 直接注入 Customize 拿到的是工厂里创建的那个对象;而注入 CustomizeFactoryBean 拿到的是工厂本身。如果想获取工厂实例,可以通过 &+factoryBeanName 的方式。

FactoryBean使用及真实应用场景分享

FactoryBean使用及真实应用场景分享

整合 MyBatis

上面那个例子虽然能用 @Component 把工厂注册进容器,但这并不是它最正宗的玩法。想注册一个 bean 方法多的是,没必要这样绕。其实 FactoryBean 最大的价值在于——把第三方框架优雅地集成进 Spring。

咱们来看看 MyBatis 和 Spring 整合时是怎么做的。

MyBatis 是怎么运行的?

MyBatis 的核心是 SqlSession,所有 SQL 操作都得通过它。而 SqlSession 是由 SqlSessionFactory 造出来的。只要拿到 SqlSessionFactory,就等于拿到了 MyBatis 的全部能力。具体解析过程的细节这里不展开,核心就是通过 build() 方法创建出 SqlSessionFactory

public SqlSessionFactory build(Reader reader, String environment, Properties properties) {
    try {
        XMLConfigBuilder parser = new XMLConfigBuilder(reader, environment, properties);
        return build(parser.parse());
    } catch (Exception e) { ... }
}

那么问题来了:怎么把 SqlSessionFactory 塞进 Spring?答案就在 SqlSessionFactoryBean 这个 FactoryBean 里。

public class SqlSessionFactoryBean
    implements FactoryBean, InitializingBean, ApplicationListener{
    
    private SqlSessionFactory sqlSessionFactory;

    @Override
    public void afterPropertiesSet() throws Exception {
        // 各种校验...
        this.sqlSessionFactory = buildSqlSessionFactory();
    }

    @Override
    public SqlSessionFactory getObject() throws Exception {
        if (this.sqlSessionFactory == null) {
            afterPropertiesSet();
        }
        return this.sqlSessionFactory;
    }

    @Override
    public Class getObjectType() {
        return this.sqlSessionFactory == null ? SqlSessionFactory.class : this.sqlSessionFactory.getClass();
    }

    @Override
    public boolean isSingleton() {
        return true;
    }
}

你看,afterPropertiesSet() 里调用了 buildSqlSessionFactory() 来创建 SqlSessionFactorygetObject() 再把创建好的实例返回。这样,只要在 Spring 配置里(XML 或 JavaConfig)声明这个 SqlSessionFactoryBean,就能把 MyBatis 的核心组件无缝挂载到容器里,后面直接注入 SqlSessionFactory 干活就行。

总结

FactoryBean 本质上是 Spring 在初始化阶段创建 bean 的一个“定制工厂”。个人觉得它更像一个插件接口——能把第三方的类以非常优雅的方式加载到 Spring 容器中。当然,它的用途不止于此,还有不少高级玩法值得深挖。

本文转载于:https://www.jb51.net/program/364868m5n.htm 如有侵犯,请联系zhengruancom@outlook.com删除。
免责声明:正软商城发布此文仅为传递信息,不代表正软商城认同其观点或证实其描述。

热门关注