Spring中接口FactoryBean作用及说明

 更新时间:2026年05月30日 09:59:44   作者:张井天  
这篇文章主要介绍了Spring中接口FactoryBean作用及说明,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教

简述

Spring 容器中有两种bean :

  • 普通 Bean:Spring 使用反射机制,利用Class 属性来实例化 Bean,放置到容器中
  • 工厂Bean (实现 FactoryBean): 当 Bean 的实例化过程比较复杂是,如果按照传统的方式(XML),则需要提供大量的配置信息, 采用编码的方式创建更加优雅,用户可以通过实现 org.Springframework.bean.factory.FactoryBean 定制 bean 实例化过程

FactoryBean接口对于Spring框架来说占有重要的地位,Spring 自身就提供了很多FactoryBean的实现。它们隐藏了实例化一些复杂bean的细节,给上层应用带来了便利。

从Spring 3.0 开始, FactoryBean开始支持泛型,即接口声明改为FactoryBean 的形式。

Spring 官方文档中对 FactoryBean介绍

官方地址:https://docs.spring.io/spring-framework/docs/current/reference/html/core.html#beans-factory-extension-factorybean

You can implement the org.springframework.beans.factory.FactoryBean interface for objects that are themselves factories.

The FactoryBean interface is a point of pluggability into the Spring IoC container’s instantiation logic. If you have complex initialization code that is better expressed in Java as opposed to a (potentially) verbose amount of XML, you can create your own FactoryBean, write the complex initialization inside that class, and then plug your custom FactoryBean into the container.

The FactoryBean interface provides three methods:

  • T getObject(): Returns an instance of the object this factory creates. The instance can possibly be shared, depending on whether this factory returns singletons or prototypes.
  • boolean isSingleton(): Returns true if this FactoryBean returns singletons or false otherwise. The default implementation of this method returns true.
  • Class<?> getObjectType(): Returns the object type returned by the getObject() method or null if the type is not known in advance.

The FactoryBean concept and interface are used in a number of places within the Spring Framework. More than 50 implementations of the FactoryBean interface ship with Spring itself.

When you need to ask a container for an actual FactoryBean instance itself instead of the bean it produces, prefix the bean’s id with the ampersand symbol (&) when calling the getBean() method of the ApplicationContext. So, for a given FactoryBean with an id of myBean, invoking getBean(“myBean”) on the container returns the product of the FactoryBean, whereas invoking getBean(“&myBean”) returns the FactoryBean instance itself.

简述:

1.Spring 提供了 FactoryBean接口 供我们实现,用于创建复杂的 Bean 对象, 避免复杂的XML配置

2.FactoryBean 中提供三个 方法:

  • T getObject() : 返回该实现真正创建的 Bean, 非 FactoryBean 本身
  • boolean isSingleton() : 决定 getObject() 是单例 还是 原型(多例),默认是单例
  • Class<?> getObjectType() : 返回 getObject() 对象 Class

3.Spring 框架内部 也有50多个关于 FactoryBean 的实现;

4.获取对象

  • 当获取 FactoryBean 创建的时对象, 可以使用 getBean(“myBean”);
  • 当获取 FactoryBean 对象时,需使用 getBean(“&myBean”)

实战

MySqlSession类:后续交与 MySqlSessionFactory 初始化

package com.lot.learn.spring.factorybean;

import lombok.Data;

@Data
public class MySqlSession {

    private Long id;

    public MySqlSession(Long id) {
        this.id = id;
    }
}

MySqlSessionFactory 实现 FactoryBean, 用于创建 MySqlSession

package com.lot.learn.spring.factorybean;

import lombok.Data;
import org.springframework.beans.factory.FactoryBean;

@Data
public class MySqlSessionFactory implements FactoryBean<MySqlSession> {

    private Long id;

    private Long sessionId;


    @Override
    public MySqlSession getObject() {
        return new MySqlSession(sessionId);
    }

    @Override
    public Class<?> getObjectType() {
        return MySqlSession.class;
    }

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

spring-factorybean.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd">
    <beans>
        <bean id="mySqlSession" class="com.lot.learn.spring.factorybean.MySqlSessionFactory" >
            <property name="id" value= "9999" />
            <property name="sessionId" value= "1" />
        </bean>
    </beans>
</beans>

Maven 配置 dependencies

<dependencies>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context</artifactId>
      <version>5.2.9.RELEASE</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-jdbc</artifactId>
      <version>5.2.9.RELEASE</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-test</artifactId>
      <version>5.2.9.RELEASE</version>
    </dependency>
  </dependencies>

测试类: TestFactoryBean

package factorybean;

import com.lot.learn.spring.factorybean.MySqlSession;
import com.lot.learn.spring.factorybean.MySqlSessionFactory;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "classpath*:spring-factorybean.xml" })
public class TestFactoryBean {


    @Autowired
    private MySqlSessionFactory userFactory1;

    @Autowired
    private MySqlSession mySqlSession1;

    @Autowired
    private ApplicationContext context;

    @Test
    public void test() {
        System.out.println("factory.getId() = " + userFactory1.getId());
        // 我们并没有配置 MySqlSession 仍可以注入
        System.out.println("mySqlSession.getId() = " + mySqlSession1.getId());

        // by Type
        MySqlSession mySqlSession2 = context.getBean(MySqlSession.class);
        MySqlSessionFactory userFactory2 = context.getBean(MySqlSessionFactory.class);

        // by name
        MySqlSession mySqlSession3 = (MySqlSession) context.getBean("mySqlSession");
        MySqlSessionFactory userFactory3 = (MySqlSessionFactory) context.getBean("&mySqlSession");

		// 以下都是 true
        System.out.println("mySqlSession1 == mySqlSession2 :" + (mySqlSession1 == mySqlSession1));
        System.out.println("userFactory1 == userFactory2 :" + (userFactory1 == userFactory1));

        System.out.println("mySqlSession2 == mySqlSession3 :" + (mySqlSession2 == mySqlSession3));
        System.out.println("userFactory2 == userFactory3 :" + (userFactory2 == userFactory3));
    }
}

测试类执行结果

根据打印结果看, 已经验证上述问题

factory.getId() = 9999
mySqlSession.getId() = 1
mySqlSession1 == mySqlSession2 :true
userFactory1 == userFactory2 :true
mySqlSession2 == mySqlSession3 :true
userFactory2 == userFactory3 :true

代替方案

现阶段使用 FactoryBean 创建对象的使用习惯越来越少, 有很多其他更方便创建方式:

  • @Configuration和@Bean注解配合,也可以用来创建bean,和FactoryBean的作用基本相同。但是@Bean功能更强大一些,可以支持懒加载,设置作用域等。
  • @Component 也可

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • 解决Mybatis-Plus中分页插件Page中total=0的问题

    解决Mybatis-Plus中分页插件Page中total=0的问题

    在使用Mybatis-Plus进行分页查询时,如果遇到`total=0`的情况,即使查询到了数据,也无法正确分页,这通常是由于依赖版本问题导致的,对于低版本,需要手动配置分页拦截器;对于高版本,可能需要添加特定的依赖配置来解决这个问题
    2025-11-11
  • Spark SQL关于性能调优选项详解

    Spark SQL关于性能调优选项详解

    这篇文章将为大家详细讲解有关Spark SQL性能调优选项,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获
    2023-02-02
  • Java多线程工具CompletableFuture的使用教程

    Java多线程工具CompletableFuture的使用教程

    CompletableFuture实现了CompletionStage接口和Future接口,前者是对后者的一个扩展,增加了异步回调、流式处理、多个Future组合处理的能力。本文就来详细讲讲CompletableFuture的使用方式,需要的可以参考一下
    2022-08-08
  • 如何使用JDBC实现工具类抽取

    如何使用JDBC实现工具类抽取

    这篇文章主要介绍了如何使用JDBC实现工具类抽取,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-02-02
  • 详解在Spring Boot框架下使用WebSocket实现消息推送

    详解在Spring Boot框架下使用WebSocket实现消息推送

    这篇文章主要介绍了详解在Spring Boot框架下使用WebSocket实现消息推送,具有一定的参考价值,感兴趣的小伙伴们可以参考一下。
    2016-12-12
  • Java 协程 Quasar详解

    Java 协程 Quasar详解

    这篇文章主要介绍了Java 协程 Quasar详解,文章围绕主题展开详细的内容介绍,具有一定的参考价值,需要的小伙伴可以参考一下
    2022-07-07
  • 关于springboot集成swagger及knife4j的增强问题

    关于springboot集成swagger及knife4j的增强问题

    这篇文章主要介绍了springboot集成swagger以及knife4j的增强,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-03-03
  • 实现java文章点击量记录实例

    实现java文章点击量记录实例

    这篇文章主要为大家介绍了实现java文章点击量记录实例,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-10-10
  • 使用反射方式获取JPA Entity的属性和值

    使用反射方式获取JPA Entity的属性和值

    这篇文章主要介绍了使用反射方式获取JPA Entity的属性和值,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-02-02
  • Java8 stream流分组groupingBy的使用方法代码

    Java8 stream流分组groupingBy的使用方法代码

    对于java8的新特性groupingBy方法,相信有很多人都在工作中用过,这篇文章主要给大家介绍了关于Java8 stream流分组groupingBy的使用方法,需要的朋友可以参考下
    2024-01-01

最新评论