Spring FactoryBean浅析

简介: ​ Spring容器管理着其内部的Bean,在这些Bean中可能存在着一类特殊的Bean,这一类Bean就是FactoryBean。FactoryBean与其它的Bean不一样的地方在于它既是Bean,也能生产Bean。从容器中获取它和它产生的Bean的方式有些特殊。 #### 源码解析 ##### FactoryBean Spring提供了一个顶级接口FactoryBean用于

​ Spring容器管理着其内部的Bean,在这些Bean中可能存在着一类特殊的Bean,这一类Bean就是FactoryBean。FactoryBean与其它的Bean不一样的地方在于它既是Bean,也能生产Bean。从容器中获取它和它产生的Bean的方式有些特殊。

源码解析

FactoryBean

Spring提供了一个顶级接口FactoryBean用于描述一个FactoryBean应该具备的功能,定义如下

public interface FactoryBean<T> {

    // 该Factory生产的Bean实例
    @Nullable
    T getObject() throws Exception;

    // 该Factory生产的Bean class
    @Nullable
    Class<?> getObjectType();

    // 该Factory生产的Bean是否为单例
    default boolean isSingleton() {
        return true;
    }

该接口提供的方法并不多,也就是说FactoryBean基本的特性只有这三个。

AbstractFactoryBean

Spring提供了一个简单的实现了FactoryBean接口的抽象类,可以基于该抽象类定义我们自己的FactoryBean。

public abstract class AbstractFactoryBean<T>
        implements FactoryBean<T>, BeanClassLoaderAware, BeanFactoryAware, InitializingBean, DisposableBean {

    /** Logger available to subclasses */
    protected final Log logger = LogFactory.getLog(getClass());

    //标识生产的Bean是否为单例
    private boolean singleton = true;

    @Nullable
    private ClassLoader beanClassLoader = ClassUtils.getDefaultClassLoader();

    @Nullable
    private BeanFactory beanFactory;

    // 单例模式下,单例是否已经初始化
    private boolean initialized = false;

    // 单例模式下持有的单例
    @Nullable
    private T singletonInstance;

    // 在单例模式下,如果需要对外提供Bean,但是单例还未初始化时可以提前该实例,不过对该实例的调用依然会委托给单例,只不过是暂时缓解罢了
    @Nullable
    private T earlySingletonInstance;


    /**
     * Set if a singleton should be created, or a new object on each request
     * otherwise. Default is {@code true} (a singleton).
     */
    public void setSingleton(boolean singleton) {
        this.singleton = singleton;
    }

    @Override
    public boolean isSingleton() {
        return this.singleton;
    }

    @Override
    public void setBeanClassLoader(ClassLoader classLoader) {
        this.beanClassLoader = classLoader;
    }

    @Override
    public void setBeanFactory(@Nullable BeanFactory beanFactory) {
        this.beanFactory = beanFactory;
    }

    /**
     * Return the BeanFactory that this bean runs in.
     */
    @Nullable
    protected BeanFactory getBeanFactory() {
        return this.beanFactory;
    }

    // 返回一个类型转换器,给子类用的
    protected TypeConverter getBeanTypeConverter() {
        BeanFactory beanFactory = getBeanFactory();
        if (beanFactory instanceof ConfigurableBeanFactory) {
            return ((ConfigurableBeanFactory) beanFactory).getTypeConverter();
        }
        else {
            return new SimpleTypeConverter();
        }
    }

    /**
     * 必要时提前创建单例
     */
    @Override
    public void afterPropertiesSet() throws Exception {
        if (isSingleton()) {
            this.initialized = true;
            this.singletonInstance = createInstance();
            this.earlySingletonInstance = null;
        }
    }


    // 这个方法用于给Spring提供自己生产的Bean
    // 如果是单例模式  单例已经初始化则返回单例,否则返回earlySingletonInstance暂时应付
    @Override
    public final T getObject() throws Exception {
        if (isSingleton()) {
            return (this.initialized ? this.singletonInstance : getEarlySingletonInstance());
        }
        else {
            return createInstance();
        }
    }

    // 返回单例未初始化时的替代品,注意如果返回的Bean的Class并未实现任何接口,那这步就直接报错了
    @SuppressWarnings("unchecked")
    private T getEarlySingletonInstance() throws Exception {
        Class<?>[] ifcs = getEarlySingletonInterfaces();
        if (ifcs == null) {
            throw new FactoryBeanNotInitializedException(
                    getClass().getName() + " does not support circular references");
        }
        if (this.earlySingletonInstance == null) {
            this.earlySingletonInstance = (T) Proxy.newProxyInstance(
                    this.beanClassLoader, ifcs, new EarlySingletonInvocationHandler());
        }
        return this.earlySingletonInstance;
    }

    // 返回单例
    @Nullable
    private T getSingletonInstance() throws IllegalStateException {
        Assert.state(this.initialized, "Singleton instance not initialized yet");
        return this.singletonInstance;
    }

    // 单例模式下提供销毁功能,具体如何销毁交由子类实现
    @Override
    public void destroy() throws Exception {
        if (isSingleton()) {
            destroyInstance(this.singletonInstance);
        }
    }


    // 返回生产的Bean的Class
    @Override
    @Nullable
    public abstract Class<?> getObjectType();

    // 如何创建单例交给子类实现
    protected abstract T createInstance() throws Exception;

    // 获取Bean的Class对象实现的接口数组,用于创建代理,子类可覆盖
    @Nullable
    protected Class<?>[] getEarlySingletonInterfaces() {
        Class<?> type = getObjectType();
        return (type != null && type.isInterface() ? new Class<?>[] {type} : null);
    }

    // 单例销毁时调用的销毁方法,子类可重写
    protected void destroyInstance(@Nullable T instance) throws Exception {
    }


    // 单例模式下获取Bean时如果单例尚未初始化,通过该Handler返回代理,暂时应付Spring,可为单例的实例化拖延下时间
    private class EarlySingletonInvocationHandler implements InvocationHandler {

        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            if (ReflectionUtils.isEqualsMethod(method)) {
                // Only consider equal when proxies are identical.
                return (proxy == args[0]);
            }
            else if (ReflectionUtils.isHashCodeMethod(method)) {
                // Use hashCode of reference proxy.
                return System.identityHashCode(proxy);
            }
            else if (!initialized && ReflectionUtils.isToStringMethod(method)) {
                return "Early singleton proxy for interfaces " +
                        ObjectUtils.nullSafeToString(getEarlySingletonInterfaces());
            }
            try {
                return method.invoke(getSingletonInstance(), args);
            }
            catch (InvocationTargetException ex) {
                throw ex.getTargetException();
            }
        }
    }

}

接来下看一些有意思的AbstractFactoryBean的实现类

AbstractServiceLoaderBasedFactoryBean

该类通过ServiceLoader实例化Bean,可用于SPI相关应用

public abstract class AbstractServiceLoaderBasedFactoryBean extends AbstractFactoryBean<Object>
        implements BeanClassLoaderAware {

    @Nullable
    private Class<?> serviceType;

    @Nullable
    private ClassLoader beanClassLoader = ClassUtils.getDefaultClassLoader();


    // 标识返回Bean的class
    public void setServiceType(@Nullable Class<?> serviceType) {
        this.serviceType = serviceType;
    }

    /**
     * Return the desired service type.
     */
    @Nullable
    public Class<?> getServiceType() {
        return this.serviceType;
    }

    @Override
    public void setBeanClassLoader(@Nullable ClassLoader beanClassLoader) {
        this.beanClassLoader = beanClassLoader;
    }


    // 实现父类的方法,不过依然交给了自己的抽象方法,调用完该方法后,ServiceLoader已经可以用于发现SPI实现类了
    @Override
    protected Object createInstance() {
        Assert.notNull(getServiceType(), "Property 'serviceType' is required");
        return getObjectToExpose(ServiceLoader.load(getServiceType(), this.beanClassLoader));
    }

    // 如何返回Bean交由子类实现
    protected abstract Object getObjectToExpose(ServiceLoader<?> serviceLoader);

}

接下来看看AbstractServiceLoaderBasedFactoryBean的相关实现类

ServiceLoader.png

ServiceLoaderFactoryBean
public class ServiceLoaderFactoryBean extends AbstractServiceLoaderBasedFactoryBean implements BeanClassLoaderAware {

    @Override
    protected Object getObjectToExpose(ServiceLoader<?> serviceLoader) {
        return serviceLoader;
    }

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

}

可以清晰的看到该FactoryBean产生的就是ServiceLoader实例,而通过该ServiceLoader实例我们可以获取SPI的实现类。

ServiceListFactoryBean
public class ServiceListFactoryBean extends AbstractServiceLoaderBasedFactoryBean implements BeanClassLoaderAware {

    @Override
    protected Object getObjectToExpose(ServiceLoader<?> serviceLoader) {
        List<Object> result = new LinkedList<>();
        for (Object loaderObject : serviceLoader) {
            result.add(loaderObject);
        }
        return result;
    }

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

}

该FactoryBean产生的Bean是一个装载着SPI实现类实例的List。

ServiceFactoryBean
public class ServiceFactoryBean extends AbstractServiceLoaderBasedFactoryBean implements BeanClassLoaderAware {

    @Override
    protected Object getObjectToExpose(ServiceLoader<?> serviceLoader) {
        Iterator<?> it = serviceLoader.iterator();
        if (!it.hasNext()) {
            throw new IllegalStateException(
                    "ServiceLoader could not find service for type [" + getServiceType() + "]");
        }
        return it.next();
    }

    @Override
    @Nullable
    public Class<?> getObjectType() {
        return getServiceType();
    }

}

该FactoryBean产生的Bean是发现的第一个SPI实现类实例。

使用FactoryBean

public class Student {
    private String name;

    private int age;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Student{" +
            "name='" + name + '\'' +
            ", age=" + age +
            '}';
    }
}
@Service
public class StudentFactoryBean extends AbstractFactoryBean<Student> {
    @Override
    public Class<?> getObjectType() {
        return Student.class;
    }

    @Override
    protected Student createInstance() throws Exception {
        Student student = new Student();
        student.setName("david");
        student.setAge(20);
        return student;
    }
}

将上面的StudentFactoryBean使用注解的方式注册到Spring容器中

运行如下语句

System.out.println(applicationContext.getBean("studentFactoryBean"));
System.out.println(applicationContext.getBean("&studentFactoryBean"));

输出

Student{name='david', age=20}
com.alibaba.my.StudentFactoryBean@35ef1869

可以看到如果我们通过FactoryBean默认的beanName从Spring容器中获取bean,获取到的并不是FactoryBean本身,而是由它产生的Bean(Student),要想获取FactoryBean本身,需要使用&+beanName

总结

本文介绍了Spring中FactoryBean的作用和使用方法,同时介绍了spring-beans中提供的与SPI相关的几个FactoryBean。最后介绍了FactoryBean的使用方法,需要注意的是如何正确获取FactoryBean本身和FactoryBean产生的Bean。

相关文章
|
4月前
|
Java 关系型数据库 MySQL
Spring5深入浅出篇:Spring中的FactoryBean对象
Spring5深入浅出篇:Spring中的FactoryBean对象
|
Java Spring 容器
Spring中BeanFactory和FactoryBean的区别?
一位工作了4年的小伙伴,去京东面试被问到这样一个问题,Spring中的BeanFactory和FactoryBean有什么区别?因为没有看过源码,当时就感觉这是一个文字游戏,感觉没什么区别? 那今天,我就给大家来聊清楚。另外,往期面试题解析中配套的文档我已经准备好,想获得的可以在我的煮叶简介中找到。好了,我们先来看BeanFactory。
57 0
|
4月前
|
XML Java 数据格式
spring中怎么通过静态工厂和动态工厂获取对象以及怎么通过 FactoryBean 获取对象
spring中怎么通过静态工厂和动态工厂获取对象以及怎么通过 FactoryBean 获取对象
66 0
|
4月前
|
Java 数据库连接 API
【Spring】1、Spring 框架的基本使用【读取配置文件、IoC、依赖注入的几种方式、FactoryBean】
【Spring】1、Spring 框架的基本使用【读取配置文件、IoC、依赖注入的几种方式、FactoryBean】
85 0
|
3月前
|
Java Spring
聊聊Spring中两种创建Bean的方式:BeanDefinition.setInstanceSupplier() 和 FactoryBean
聊聊Spring中两种创建Bean的方式:BeanDefinition.setInstanceSupplier() 和 FactoryBean
|
4月前
|
XML Java 数据格式
Spring5源码(8)-BeanFactory和FactoryBean的区别
Spring5源码(8)-BeanFactory和FactoryBean的区别
50 0
|
4月前
|
XML Java 数据格式
③【Spring】整合第三框架的常用机制:FactoryBean
③【Spring】整合第三框架的常用机制:FactoryBean
70 0
|
10月前
|
XML Java 数据格式
Spring中BeanFactory和FactoryBean详解
Spring中BeanFactory和FactoryBean详解
239 1
|
Java Spring 容器
【Spring源码】 BeanFactory和FactoryBean是什么?
面试官:“看过Spring源码吧,简单说说Spring中BeanFactory和FactoryBean的区别是什么?”
17456 6
【Spring源码】 BeanFactory和FactoryBean是什么?
|
Java C++ Spring
Spring5源码 - 08 BeanFactory和FactoryBean 源码解析 & 使用场景
Spring5源码 - 08 BeanFactory和FactoryBean 源码解析 & 使用场景
132 0