一、bean的类型

普通bean,工厂bean

FactoryBean是重点

FactoryBean 是 Spring 提供的一个特殊接口

  • 普通 Bean:直接返回对象本身
  • FactoryBean:返回 它 “生产” 出来的对象(不是自己)

简单说:FactoryBean = 工厂 + Bean,它帮 Spring 造复杂对象。

源码分析

public interface FactoryBean<T> {
    // 返回目标对象(核心创建逻辑)
    T getObject() throws Exception;

    // 返回目标对象类型
    Class<?> getObjectType();

    // 是否单例(Spring5+ 默认 true)
    default boolean isSingleton() {
        return true;
    }
}

下面我们写一个例子

1.先写一个普通类(要被工厂生产的产品)

// 这是我们要生产的“产品”类
public class Car {
    private String name;
    private int price;

    // 构造、getter、setter、toString
    public Car(String name, int price) {
        this.name = name;
        this.price = price;
    }

    @Override
    public String toString() {
        return "Car{name='" + name + "', price=" + price + "}";
    }
}

2. 写一个 FactoryBean(工厂 Bean)

import org.springframework.beans.factory.FactoryBean;
import org.springframework.stereotype.Component;

// 交给 Spring 管理
@Component
public class CarFactoryBean implements FactoryBean<Car> {

    // 核心方法:返回“生产出来的对象”
    @Override
    public Car getObject() throws Exception {
        // 这里可以写复杂的创建逻辑:连接数据库、读取配置、反射创建...
        System.out.println("CarFactoryBean 开始生产 Car 对象...");
        return new Car("特斯拉Model 3", 250000);
    }

    // 返回产品类型
    @Override
    public Class<?> getObjectType() {
        return Car.class;
    }

    // 是否单例(默认true)
    @Override
    public boolean isSingleton() {
        return true;
    }
}

3.Spring配置类

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

@Configuration
@ComponentScan
public class SpringConfig {
}

4.测试类

import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class Test {
    public static void main(String[] args) {
        ApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class);

        // 重点:获取的是 Car,不是 CarFactoryBean!
        Car car = context.getBean(Car.class);
        System.out.println("获取到的对象:" + car);

        // 如果想获取工厂本身,加 & 前缀
        CarFactoryBean factoryBean = (CarFactoryBean) context.getBean("&carFactoryBean");
        System.out.println("获取到工厂本身:" + factoryBean);
    }
}

运行结果

CarFactoryBean 开始生产 Car 对象...
获取到的对象:Car{name='特斯拉Model 3', price=250000}
获取到工厂本身:org.example.factorybean.CarFactoryBean@6f43c82

总结一下

getBean(Car.class)    拿到的是产品(Car)

Spring自动调用getObject()生成对象

想拿工厂本身必须加

context.getBean("&carFactoryBean")

必须实现的三个方法:1.getObject() 2.getgetObjectType()   3.isSingleton()

什么时候用FactoryBean:

  • 对象创建特别复杂(需要很多步骤、配置、依赖)
  • 不想把复杂逻辑写在配置文件里
  • 框架底层常用(MyBatis 的 SqlSessionFactoryBean 就是经典例子)

更多推荐