FactoryBean的使用及底层工作原理分析

 更新时间:2026年05月30日 10:10:28   作者:冰点.  
FactoryBean接口解析与使用示例,详解Spring框架中FactoryBean的作用和底层原理,以及如何通过FactoryBean实现对象的动态创建is装配is代理is包装和生命周期管理

大家好,我是冰点,本节我们通过对FactoryBean 接口源码解析,以及使用示例剖析,让大家3分钟了解FactoryBean的作用和底层工作原理。以及FactoryBean的使用场景,学以致用。

FactoryBean是Spring框架中的一个接口,用于创建和管理其他Bean实例的对象。

FactoryBean的底层工作原理是通过实现FactoryBean接口并实现其中的方法来创建和管理Bean实例。

1.FactoryBean接口源码解析

public interface FactoryBean<T> {
    
    // 获取由此工厂创建的对象实例
    T getObject() throws Exception;

    // 获取由此工厂创建的对象实例的类型
    Class<?> getObjectType();

    // 判断由此工厂创建的对象实例是否为单例模式
    default boolean isSingleton() {
        return true;
    }
}
  • getObject()方法:获取由此工厂创建的对象实例,可以在此方法中编写自定义的创建逻辑,例如从外部资源获取对象实例。
  • getObjectType()方法:获取由此工厂创建的对象实例的类型,Spring框架可以利用此方法来确定依赖注入时需要注入的具体类型。
  • isSingleton()方法:判断由此工厂创建的对象实例是否为单例模式。默认情况下,FactoryBean创建的对象实例是单例模式,但是可以通过覆盖此方法来改变对象实例的作用域。

2.FactoryBean使用代码示例

一个简单的FactoryBean示例代码,咱们创建一个随机数生成器的实例:

import java.util.Random;
import org.springframework.beans.factory.FactoryBean;

public class RandomNumberFactoryBean implements FactoryBean<Random> {

    private int seed;

    public void setSeed(int seed) {
        this.seed = seed;
    }

    @Override
    public Random getObject() throws Exception {
        return new Random(seed);
    }

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

    @Override
    public boolean isSingleton() {
        return true;
    }
}
  • RandomNumberFactoryBean实现了FactoryBean接口,并实现了getObject()、getObjectType()和isSingleton()方法。
  • 在getObject()方法中,它返回了一个由seed属性指定的随机数生成器的实例。在getObjectType()方法中,它返回了该实例的类型,即Random类。在isSingleton()方法中,它指定了该实例是一个单例模式的Bean。

要使用注解方式实例化RandomNumberFactoryBean,可以使用@Configuration@Bean注解。

首先,创建一个配置类,使用@Configuration注解标记该类为配置类。然后,在该类中创建一个用于实例化RandomNumberFactoryBean@Bean方法,如下所示:

import java.util.Random;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class AppConfig {

    @Bean
    public RandomNumberFactoryBean myRandom() {
        RandomNumberFactoryBean factoryBean = new RandomNumberFactoryBean();
        factoryBean.setSeed(12345);
        return factoryBean;
    }
}

在这个示例中,AppConfig类使用@Configuration注解标记为配置类。然后,它定义了一个名为myRandom@Bean方法,该方法返回一个RandomNumberFactoryBean实例,并为其设置seed属性值为12345。

最后,在Spring应用程序中,使用AnnotationConfigApplicationContext类来加载该配置类,如下所示:

import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class MyApp {

    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
        Random random = context.getBean("myRandom", Random.class);
        int number = random.nextInt();
        System.out.println("Random number: " + number);
        context.close();
    }
}

在这个示例中,MyApp类使用AnnotationConfigApplicationContext类来加载AppConfig配置类,并从容器中获取myRandom Bean实例。然后,它使用该实例生成一个随机数,并将其输出到控制台。

使用注解方式实例化RandomNumberFactoryBean与使用XML配置方式实例化它的区别在于,我们可以在@Bean方法中直接创建RandomNumberFactoryBean实例,并为其设置属性值,而不需要使用XML配置文件。这种方式更加便捷和灵活,可以更方便地进行测试和修改。

3. 核心几个点

  • 当Spring容器启动时,它会扫描应用程序中的所有Bean定义,并实例化那些需要实例化的Bean。如果遇到实现了FactoryBean接口的Bean定义,Spring将会为该Bean创建一个特殊的代理对象,以便在需要时调用FactoryBean的方法来创建实际的Bean实例。
  • 当需要使用由FactoryBean创建的Bean时,Spring将会调用代理对象的getObject()方法来获取实际的Bean实例。如果需要,Spring还可以调用代理对象的getObjectType()方法来确定实际Bean实例的类型。
  • 如果FactoryBean创建的Bean是单例模式,那么Spring将在第一次调用getObject()方法时创建实例,并将其缓存起来。以后每次调用getObject()方法时,都会返回同一个实例。如果FactoryBean创建的Bean不是单例模式,则每次调用getObject()方法时都会创建一个新的实例。

4. FactoryBean 到底能干什么

FactoryBean允许我们在创建Bean实例时编写自定义的逻辑,并且可以通过其返回的实际Bean实例类型来实现更精细的依赖注入。同时,Spring框架还提供了一些内置的FactoryBean实现,例如ProxyFactoryBeanJndiObjectFactoryBean,可以帮助我们更方便地创建一些常见的Bean实例。

FactoryBean 是 Spring 框架中的一个接口,它可以创建和管理其他对象的实例。通过实现 FactoryBean 接口,可以自定义对象的创建过程,可以实现一些特殊的功能。

FactoryBean 主要有以下作用:

  • 动态创建对象:FactoryBean 可以根据配置的参数和条件,动态地创建对象。这样可以根据不同的情况创建不同的对象实例。
  • 对象的装配和初始化:FactoryBean 可以对创建的对象进行配置和初始化,可以通过设置不同的属性值或者调用不同的方法来进行装配和初始化。
  • 对象的代理和包装:通过 FactoryBean 可以对创建的对象进行代理和包装,可以动态地增加或修改对象的功能。
  • 对象的生命周期管理:FactoryBean 可以管理所创建的对象的生命周期,可以在对象创建前后执行一些操作,可以在需要时销毁对象。
  • 对象的缓存和复用:FactoryBean 可以实现对象的缓存和复用,可以避免重复创建对象,提高性能。

下面给出几种常见的 FactoryBean 的使用示例:

  1. 动态创建对象
public class MyFactoryBean implements FactoryBean<Object> {
    
    @Override
    public Object getObject() throws Exception {
        // 根据配置或条件动态创建对象
        if (someCondition) {
            return new MyObject();
        } else {
            return new AnotherObject();
        }
    }

    @Override
    public Class<?> getObjectType() {
        // 返回实际创建的对象的类型
        return Object.class;
    }

    @Override
    public boolean isSingleton() {
        // 返回是否为单例对象
        return true;
    }
}
  1. 对象的装配和初始化
public class MyFactoryBean implements FactoryBean<MyObject> {

    private String name;
    private int age;

    @Override
    public MyObject getObject() throws Exception {
        // 创建对象并进行装配和初始化
        MyObject myObject = new MyObject();
        myObject.setName(name);
        myObject.setAge(age);
        return myObject;
    }

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

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

    // 设置属性值的方法
    public void setName(String name) {
        this.name = name;
    }

    public void setAge(int age) {
        this.age = age;
    }
}
  1. 对象的代理和包装
public class MyFactoryBean implements FactoryBean<MyObject> {

    private MyObject target;

    @Override
    public MyObject getObject() throws Exception {
        // 对目标对象进行代理和包装
        MyObjectProxy proxy = new MyObjectProxy(target);
        return proxy.getProxy();
    }

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

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

    // 设置目标对象的方法
    public void setTarget(MyObject target) {
        this.target = target;
    }
}
  1. 对象的缓存和复用
public class MyFactoryBean implements FactoryBean<MyObject> {

    private static final Map<String, MyObject> objectCache = new ConcurrentHashMap<>();

    private String key;

    @Override
    public MyObject getObject() throws Exception {
        // 根据 key 从缓存中获取对象,如果不存在则创建并放入缓存
        MyObject myObject = objectCache.get(key);
        if (myObject == null) {
            myObject = new MyObject();
            objectCache.put(key, myObject);
        }
        return myObject;
    }

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

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

    // 设置 key 值的方法
    public void setKey(String key) {
        this.key = key;
    }
}
  1. 对象的延迟初始化
public class MyFactoryBean implements FactoryBean<MyObject>, InitializingBean {

    private MyObject myObject;

    @Override
    public MyObject getObject() throws Exception {
        return myObject;
    }

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

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

    // 在初始化时创建对象
    @Override
    public void afterPropertiesSet() throws Exception {
        myObject = new MyObject();
        // 执行初始化操作
        myObject.init();
    }
}
  1. 对象的销毁和资源释放
public class MyFactoryBean implements FactoryBean<MyObject>, DisposableBean {

    private MyObject myObject;

    @Override
    public MyObject getObject() throws Exception {
        return myObject;
    }

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

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

    // 在销毁时释放资源
    @Override
    public void destroy() throws Exception {
        // 执行销毁操作
        myObject.release();
    }
}

总结

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

相关文章

最新评论