zoukankan      html  css  js  c++  java
  • 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方法的那些事,欢迎关注。

    一个爱写文章的程序员,欢迎关注我的公众号“北漂程序员”。我有故事,你有酒吗
  • 相关阅读:
    第一节,Django+Xadmin打造上线标准的在线教育平台—创建用户app,在models.py文件生成3张表,用户表、验证码表、轮播图表
    Tensorflow 错误:Unknown command line flag 'f'
    Python 多线程总结
    Git 强制拉取覆盖本地所有文件
    Hive常用函数 傻瓜学习笔记 附完整示例
    Linux 删除指定大小(范围)的文件
    Python 操作 HBase —— Trift Trift2 Happybase 安装使用
    梯度消失 梯度爆炸 梯度偏置 梯度饱和 梯度死亡 文献收藏
    Embedding 文献收藏
    深度学习在CTR预估中的应用 文献收藏
  • 原文地址:https://www.cnblogs.com/teach/p/14951920.html
Copyright © 2011-2022 走看看