spring中FactoryBean是什么bean

前言

在spring中FactoryBean绝对是一种神奇的存在,和BeanFactory经常混淆,而且成为面试过程中经常被问到的问题,其实FactoryBean和BeanFactory很好理解,掌握一定的技巧即可。

初识

FactoryBean翻译过来是工厂Bean,BeanFactory翻译过来是Bean工厂,前者是bean工厂beanFactory中的一个bean,只不过这个bean和一般的bean不一样,它有着自己的特殊之处,特殊在什么地方那,在spring中提供了FactoryBean的接口,

package org.springframework.beans.factory;

import org.springframework.lang.Nullable;


public interface FactoryBean<T> {

    
    @Nullable
    T getObject() throws Exception;

    
    @Nullable
    Class<?> getObjectType();

    
    default boolean isSingleton() {
        return true;
    }

}

FactoryBean接口很简单,就提供了三个方法getObject、getObjectType、isSingleton。就是这三个方法却成为了spring中很多功能的基础,搜索整个spring的源码可以找到很多FactoryBean,除了spring自身提供的以外,在和一些框架进行集成的时候,同样有FactoryBean的影子,比如和mybatis集成的时候的SqlSessionFactoryBean,

用法

这里以springboot的环境为例演示下FactoryBean的用法,有需要源码的可关注公众号【北漂程序员】私聊我。

自定义FactoryBean,仅在getObject方法内自己new了一个Student对象,且返回该对象;重写了toString方法,为了测试用。

package com.example.myDemo.component;

import com.example.myDemo.po.Student;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.stereotype.Component;

@Component
public class MyFactoryBean implements FactoryBean<Student> {

    @Override
    public Student getObject() throws Exception {

        Student student=new Student();
        return student;
    }

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

    @Override
    public String toString() {
        return "MyFactoryBean{}";
    }
}

下面是Student类,很简单就两个属性且重写了toString方法,

package com.example.myDemo.po;

public class Student {
    private String name;
    private String code;

    public Student(String name, String code) {
        this.name = name;
        this.code = code;
    }

    public Student() {
    }

    @Override
    public String toString() {
        return "Student{}";
    }
}

下面就是测试的方法了,

package com.example.myDemo;

import com.example.myDemo.component.MyFactoryBean;
import com.example.myDemo.po.Student;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration;
import org.springframework.context.ApplicationContext;

@SpringBootApplication(exclude={DataSourceAutoConfiguration.class, HibernateJpaAutoConfiguration.class})
public class MyDemoApplication {

    public static void main(String[] args) {
        ApplicationContext ac=SpringApplication.run(MyDemoApplication.class, args);

        //获得Student对象
        Student stu=(Student) ac.getBean("myFactoryBean");
        //获得MyFactoryBean对象
        MyFactoryBean myFactoryBean=(MyFactoryBean) ac.getBean("&myFactoryBean");
        System.out.println("stu:"+stu);
        System.out.println("myFactoryBean:"+myFactoryBean);

    }

}

先看下打印结果,

打印结果很奇怪通过“myFactoryBean”获得了Student对象,通过“&myFactoryBean”获得了MyFactoryBean对象。为什么会这样

功能解释

看了上面的输出结果很多小伙伴都很诧异,没错这就是FactoryBean的神奇,通俗点讲FactoryBean是一个工厂bean,它是一种可以生产bean的bean,通过其getObejct方法生产bean。当然不论是FactoryBean还是FactoryBean生产的bean都是受spring管理的这点是没有问题的,不然通过getBean方法是拿不到的。

上面讲了那么多到底FactoryBean的用处是什么,前面讲到FactroyBean的作用是生产一个Bean,这里有一个疑问spring就是用来生产bean和管理bean的,为什么还要有FactoryBean,FactoryBean的真正目的是让开发者自己去定义那些复杂的bean并交给spring管理,如果bean中要初始化很多变量,而且要进行许多操作,那么使用spring的自动装配是很难完成的,所以spring的开发者把这些工作交给了我们。一个比较常见的例子是,在mybatis和spring集成的时候便有这样一个FactoryBean,名字叫SqlSessionFactoryBean,这个FactoryBean的目的就是返回一个spring管理的SqlSessionFactory,使用过mybatis的都知道要创建一个sqlSessionFactory需要配置很多属性,所以便有了SqlSessionFactoryBean,下面看下SqlSessionFactoryBean,

看下sqlSessionFactoryBean的getObejct方法

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

        return this.sqlSessionFactory;
    }

getObejctType方法

public Class<? extends SqlSessionFactory> getObjectType() {
        return this.sqlSessionFactory == null ? SqlSessionFactory.class : this.sqlSessionFactory.getClass();
    }

isSingleton方法

public boolean isSingleton() {
        return true;
    }

总结

本篇文章主要带小伙伴了解了FactoryBean这种特殊的Bean,它的作用就是生产Bean。这里有个疑问在使用getBean方法的时候,为什么传入“myFactoryBean”和“&MyFactoryBean”两个值返回值一个是FactoryBean生产的bean,一个是FactorBean那,下篇通过源码来揭秘,揭秘getObjectForBeanInstance方法的那些事,欢迎关注。

posted @ 2021-07-01 17:55  良工说技术  阅读(1705)  评论(0编辑  收藏  举报