FactoryBean和BeanFactory的区别

FactoryBean :是一个工厂Bean,可以生成某一个类型Bean实例,它最大的一个作用是:可以让我们自定义Bean的创建过程。
BeanFactory :是Spring容器中的一个基类,也是很重要的一个类,在BeanFactory中可以创建和管理Spring容器中的Bean,它对于Bean的创建有一个统一的流程。

FactoryBean

看看源码是怎么说的

package org.springframework.beans.factory;

import org.springframework.lang.Nullable;

public interface FactoryBean<T> {
    String OBJECT_TYPE_ATTRIBUTE = "factoryBeanObjectType";
    
	//返回实例bean
    @Nullable
    T getObject() throws Exception;
    
	//返回bean的类型
    @Nullable
    Class<?> getObjectType();
    
	//是否是单例
    default boolean isSingleton() {
        return true;
    }
}

自己写 FactoryBean 的实现

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd
        " >
    <context:component-scan base-package="com.luo.dao"/>

</beans>
@Component("daoFactoryBean")//daoFactoryBean:得到是当前产生的对象,&daoFactoryBean:得到的是当前对象
public class DaoFactoryBean implements FactoryBean<TempFactoryBean> {
    /*
     * 实现了factoryBean接口
     * spring中会存在两个bean
     * 一个是当前对象(&+当前类的名字),
     * 一个是getObject返回值  `
     **/
    public void test(){
        System.out.println("DaoFactoryBean");
    }
    @Override
    public boolean isSingleton() {
        return true;
    }

    //返回的一个bean
    @Override
    public TempFactoryBean getObject() throws Exception {
        //这里可以进行很多业务逻辑处理
        return new TempFactoryBean();
    }

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

引入外部的资源

public class TempFactoryBean {
    public void test(){
        System.out.println("TempFactoryBean");
    }
}

测试一下

public class Test02 {
    public static void main(String[] args) throws Exception {
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spingmvc.xml");
        DaoFactoryBean daoFactoryBean = (DaoFactoryBean) applicationContext.getBean("&daoFactoryBean");
        TempFactoryBean tempFactoryBean = (TempFactoryBean) applicationContext.getBean("daoFactoryBean");
        daoFactoryBean.test();
        tempFactoryBean.test();
    }
}

输出

"C:\Program Files\Java\jdk1.8.0_144\bin\java.exe" "-javaagent:D:\IntelliJ IDEA\IntelliJ IDEA 2018.2.4\lib\idea_rt.jar=52065:D:\IntelliJ IDEA\IntelliJ IDEA 2018.2.4\bin" -Dfile.encoding=UTF-8 -classpath "C:\Program Files\Java\jdk1.8.0_144\jre\lib\charsets.jar;C:\Program Files\Java\jdk1.8.0_144\jre\lib\deploy.jar;C:\Program Files\Java\jdk1.8.0_144\jre\lib\ext\access-bridge-64.jar;C:\Program 
DaoFactoryBean
TempFactoryBean

Process finished with exit code 0

根据结果可以知道,一个 实现了factoryBean接口的对象,会产生两个bean,一个是当前的对象,一个是当前对象生产的实例。要获取这个实例,就用当前对象的beanName获取,如果要获取当前对象,就用 &beanName 获取。

为什么要这么设计呢?
因为如果在xml中配置bean,此bean有很多属性或者说有第三方的依赖,就会配置大量的属性,大量的引用,太过于复杂。经典的例子有 MybatisSqlSessionFactoryBean

public class MybatisSqlSessionFactoryBean implements FactoryBean<SqlSessionFactory>, InitializingBean, ApplicationListener<ApplicationEvent> {
    private static final Logger LOGGER = LoggerFactory.getLogger(MybatisSqlSessionFactoryBean.class);
    private static final ResourcePatternResolver RESOURCE_PATTERN_RESOLVER = new PathMatchingResourcePatternResolver();
    private static final MetadataReaderFactory METADATA_READER_FACTORY = new CachingMetadataReaderFactory();
    private Resource configLocation;
    private MybatisConfiguration configuration;
    private Resource[] mapperLocations;
    private DataSource dataSource;
    private TransactionFactory transactionFactory;
    private Properties configurationProperties;
    private SqlSessionFactory sqlSessionFactory;
    private boolean failFast;
    private Interceptor[] plugins;
    private TypeHandler<?>[] typeHandlers;
    private String typeHandlersPackage;
    private Class<?>[] typeAliases;
    private String typeAliasesPackage;
    private Class<?> typeAliasesSuperType;
    private LanguageDriver[] scriptingLanguageDrivers;
    private Class<? extends LanguageDriver> defaultScriptingLanguageDriver;
    private DatabaseIdProvider databaseIdProvider;
    private Class<? extends VFS> vfs;
    private Cache cache;
    private ObjectFactory objectFactory;
    private ObjectWrapperFactory objectWrapperFactory;
    private String typeEnumsPackage;
    private GlobalConfig globalConfig;

    public MybatisSqlSessionFactoryBean() {
    }

  
    public void setDatabaseIdProvider(DatabaseIdProvider databaseIdProvider) {
        this.databaseIdProvider = databaseIdProvider;
    }

    public void setTypeAliasesPackage(String typeAliasesPackage) {
        this.typeAliasesPackage = typeAliasesPackage;
    }

    public void setTypeAliasesSuperType(Class<?> typeAliasesSuperType) {
        this.typeAliasesSuperType = typeAliasesSuperType;
    }

    public void setTypeHandlersPackage(String typeHandlersPackage) {
        this.typeHandlersPackage = typeHandlersPackage;
    }

    public void setTypeHandlers(TypeHandler... typeHandlers) {
        this.typeHandlers = typeHandlers;
    }

    public void setTypeAliases(Class... typeAliases) {
        this.typeAliases = typeAliases;
    }

 
    public void setConfigLocation(Resource configLocation) {
        this.configLocation = configLocation;
    }

    public void setConfiguration(MybatisConfiguration configuration) {
        this.configuration = configuration;
    }

    public MybatisConfiguration getConfiguration() {
        return this.configuration;
    }

    public void setMapperLocations(Resource... mapperLocations) {
        this.mapperLocations = mapperLocations;
    }

    public void setConfigurationProperties(Properties sqlSessionFactoryProperties) {
        this.configurationProperties = sqlSessionFactoryProperties;
    }

    public void setDataSource(DataSource dataSource) {
        if (dataSource instanceof TransactionAwareDataSourceProxy) {
            this.dataSource = ((TransactionAwareDataSourceProxy)dataSource).getTargetDataSource();
        } else {
            this.dataSource = dataSource;
        }

    }

    public void setTransactionFactory(TransactionFactory transactionFactory) {
        this.transactionFactory = transactionFactory;
    }

    protected SqlSessionFactory buildSqlSessionFactory() throws Exception {

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

        return this.sqlSessionFactory;
    }

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

    public boolean isSingleton() {
        return true;
    }

    public void setTypeEnumsPackage(final String typeEnumsPackage) {
        this.typeEnumsPackage = typeEnumsPackage;
    }

    public void setGlobalConfig(final GlobalConfig globalConfig) {
        this.globalConfig = globalConfig;
    }
}
						.......
						.......
						.......

我们在使用 SqlSessionFactoryBean 的时候很简单,但是底层却进行了大量的处理。
以后如果遇到大量的配置或者说有依赖第三方,可以考虑使用这种方式

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

罗罗的1024

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值