• FactoryBean原理


    一、FactoryBean代码

    public interface FactoryBean<T> {
    //返回的对象实例
        T getObject() throws Exception;
        //Bean的类型
        Class<?> getObjectType();
        //true是单例,false是非单例  在Spring5.0中此方法利用了JDK1.8的新特性变成了default方法,返回true
        boolean isSingleton();
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    二、FactoryBean作用

    1、FactoryBean也是一个bean,通过容器获取bean时getBean()时,对于FactoryBean类型,会调用getObject()方法生成自定义类型的bean。
    2、getObject()生成的bean,这个bean的BeanDefination不在容器中,那为什么我们通过容器的getBean()时,为什么有能获得这个bean呢?

     FactoryBeanService bean = applicationContext.getBean(FactoryBeanService.class);
    FactoryBeanService bean1 = applicationContext.getBean("factoryBeanLearn", FactoryBeanService.class);
    System.out.println(bean==bean1);
    
    • 1
    • 2
    • 3

    三、底层源码

    FactoryBean生成的对象保存在factoryBeanObjectCache中
    循环Spring容器中所有的beanNames,再根据beanName获取对应的Bean实例,判断获取的Bean实例是不是FactoryBean类型的Bean,如果是,则调用Bean的getObjectType方法获取Class,将获取到的Class和传入的Class进行匹配,如果匹配到,则将此beanName和传入的Class建立一个映射关系。再根据beanName获取到Spring容器中对应的Bean,调用Bean的getObject方法来获取对应的实例。

    FactoryBean
    1、它也是一个Bean ,也是在Spring容器中,它的创建于其他bean对象没有任何区别。
    2、只是在通过容器获取bean的时候,传递的beanName需要在前面加上&,才能正常返回对应的Bean
    3、如果只是通过getBean(beanName)的话,获取到的是FactoryBean#getObject()中返回的bean,这个bean也保存在spring容器中,但是与普通的bean保存的位置不同,不是在一级缓存singletonObjects中,而是在factoryBeanObjectCache中。
    4、如果想要获取FactoryBean的话,需要在beanName前面加&,才可以,getBean(“&”+beanName)。

    底层代码原理

    1、 根据beanName获取实例

    getBean(BeanName)–>doGetBean()–>getObjectForBeanInstance(sharedInstance, name, beanName, null);–>getObjectFromFactoryBean(factory, beanName, !synthetic);
    –> doGetObjectFromFactoryBean(factory, beanName);–>factory.getObject();
    1、根部BeanName找到FactoryBean
    2、判断beanInstance是否是Factorybean或者beanName 是否以&开头,是的话,直接返回,
    3、不是的话,查看factoryBeanObjectCache是否存在实例;
    4、doGetObjectFromFactoryBean(),通过FactoryBean#getObject()创建一个beanInstance,并放入到缓存中。

    2、 根据BeanType获取实例

    getBean(FactoryBeanService.class)–>resolveNamedBean(requiredType, args);–>getBeanNamesForType(requiredType);–>doGetBeanNamesForType(ResolvableType.forRawClass(type), includeNonSingletons, true);–>isFactoryBean(beanName, mbd);–>isTypeMatch(beanName, type);–>getSingleton(beanName, false);–> getTypeForFactoryBean((FactoryBean<?>) beanInstance);–>factoryBean.getObjectType();–>return new NamedBeanHolder(beanName, getBean(beanName, requiredType, args));

    1、遍历BeanName,判断BeanName对应的BeanDefination是否是FactoryBean
    2、如果是FactoryBean,然后判断FactoryBean#getObjectType()是否和目标Bean.class是否一致
    3、是的话,就返回对应的BeanName,然后根据BeanName返回Bean实例,与通过BeanName获取实例过程一样

  • 相关阅读:
    wxpython使用中出现的内存泄露问题
    ABAP:调用HTTP接口详解
    海量小文件数据传输如何确保安全性
    小型数据库系统开发作业
    践行这两个方法,跳出一切情绪的制约
    【数据集的制作】VOC2007数据集格式的转换(voc2yolo)与划分
    JavaScript编程基础 – 函数进阶
    猿创征文| 指针,这还拿不下你?
    swagger文档部分乱码解决,swagger文档设置自动同步到yapi
    Vue+element 商品参数业务实现
  • 原文地址:https://blog.csdn.net/riant110/article/details/125380789