美文网首页
【Spring源码】8.IOC之创建bean对象之Factory

【Spring源码】8.IOC之创建bean对象之Factory

作者: 天还下着毛毛雨 | 来源:发表于2022-01-21 15:15 被阅读0次
    image

    前言

    上一篇讲了 Bean实例化的总体流程:

    1. Bean的创建
    2. 各种信息的收集
    3. 依赖注入
    4. Bean的初始化

    Bean的创建

    其中第一步,Bean的创建方式又有以下几种:

    1. factoryMethod :
      1. FactoryBean + FactoryBean的非静态FactoryMethod
      2. 当前beanClass + 静态FactoryMethod
    2. 构造方法
      1. 带有@Autowired注解的有参构造
      2. 不带有@Autowired注解的有参构造
      3. 无参构造

    这篇主要讲FactoryMethod 方式 是如何来创建bean。

    image

    factoryMethod和构造方法创建实例 全在这个 createBeanInstance(beanName, mbd, args) 中,点进该方法。

    FactoryMethod创建Bean

    示例代码: People的实例 化 由 factoryMethodBean 的 getPeople() 来完成。

    <bean class="com.lb.springboot_simple_starter.bean.factory_method.People" factory-method="getPeople" factory-bean="factoryMethodBean"/>
    <bean id="factoryMethodBean" class="com.lb.springboot_simple_starter.bean.factory_method.FactoryMethodBean"/>
    

    如果BeanDefinition里的 FactoryMethodName 不等于空, 就采用这种方式 实例化,直接返回 实例。

    image

    点进instantiateUsingFactoryMethod方法

    image

    全部的逻辑都在这个方法中 : instantiateUsingFactoryMethod。

    1.1 是否配置了factory-bean

    首先关注下三个 局部变量:

    1. factoryBean : FactoryBean属性对应的实例。
    2. factoryClass : 要么是FactoryBean的Class,如果没配置factory-bean就是当前实例化的bean自己的class
    3. isStatic : factoryMethod 是否是静态的。配置了factory-bean就为false,要求factoryMethod为非静态的,否则, 就必须是静态的(因为没配置factoryBean 那么factoryClass就是当前实例化的bean的class, 只有静态的才能直接调用,非静态的需要实例化之后才能调用, 而当前 正处在实例化阶段, 就会导致永远无法实例化。)
    image

    1.1.1 配置了factory-bean

    1. factoryBean 就直接根据配置的factoryBeanName 从 beanFactory 直接get, 如果这个factoryBean没有实例化,就会提前触发实例化。
    2. factoryClass 为 factoryBean的class
    3. isStatic 为false
    image

    1.1.2 没配置factory-bean

    1. factoryBean 为null
    2. factoryClass 为当前实例化的bean自己的class
    3. isStatic = true
    image

    1.2 选择FactoryMethod

    1. 当配置了Factory-Bean,此时 factoryBean 有值, factoryClass 为 factoryBean的class isStatic 为false

      此时获取到的FactoryBean这个对象的类 中 方法名称等于 FactoryMethod的, 且为非 static的 方法对象。

    2. 当没配置Factory-Bean, 此时factoryBean 为null,factoryClass 为当前实例化的bean自己的class,isStatic = true

      那么这个判断 获取到的是 当前正在实例化的bean的 类中,方法名称等于 FactoryMethod的, 且为static的 方法

    image

    1.3 FactoryMethod只存在一个,直接反射调用

    当只获取到一个FactoryMethod,并且是无参的,这时候, 就直接反射调用了。

    image

    获取到方法之后, 剩下的就是 反射调用

    image image

    这里, factoryMethod.invoke(factoryBean, args),如果是静态方法,factoryBean传进来是没有值的。如果是非静态方法,那么 factoryBean是有值的。正好。

    1.4 FactoryMethod 存在多个的反射调用。

    除了无参的 FactoryMethod 之外, 还可能有重写的带有不同参数列表的 多个 同名的 FactoryMethod列表。

    此时, 就不会走 FactoryMethod 只存在一个 的 代码分支。不会直接反射,还要经过方法的筛选:

    优先选 参数列表最长,并且 参数都可以获取到的那一个

    1.4.1 首先按照FactoryMethod 的参数多少 排序,多的排在前面。

    image

    1.4.2 排序之后,参数多的先遍历

    此时存在参数,就会有获取参数的过程, 这种不会自动按照类型注入进来, 要在xml中 用<constructor-arg>指定

    <bean class="com.lb.springboot_simple_starter.bean.factory_method.People" factory-method="getPeople" factory-bean="factoryMethodBean">
        <constructor-arg ref="myBean"></constructor-arg>
    </bean>
    
    public class FactoryMethodBean {
    
        public People getPeople() {
            return new People();
        }
    
        // 带参的
        public People getPeople( MyBean zheJiang) {
            return new People();
        }
    }
    
    image

    1.4.3 反射调用 最合适的方法

    image

    最终一个bean就通过这种方式创建好并返回出去了。

    相关文章

      网友评论

          本文标题:【Spring源码】8.IOC之创建bean对象之Factory

          本文链接:https://www.haomeiwen.com/subject/bubehrtx.html