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

2022-01-21  本文已影响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就通过这种方式创建好并返回出去了。

上一篇下一篇

猜你喜欢

热点阅读