![](https://img.haomeiwen.com/i23353704/e1fcccc75182c01c.png)
前言
上一篇讲了 Bean实例化的总体流程:
- Bean的创建
- 各种信息的收集
- 依赖注入
- Bean的初始化
Bean的创建
其中第一步,Bean的创建方式又有以下几种:
- factoryMethod :
- FactoryBean + FactoryBean的非静态FactoryMethod
- 当前beanClass + 静态FactoryMethod
- 构造方法
- 带有@Autowired注解的有参构造
- 不带有@Autowired注解的有参构造
- 无参构造
这篇主要讲FactoryMethod 方式 是如何来创建bean。
![](https://img.haomeiwen.com/i23353704/e3da7730ab845530.png)
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 不等于空, 就采用这种方式 实例化,直接返回 实例。
![](https://img.haomeiwen.com/i23353704/0f12b52292ef2cf1.png)
点进instantiateUsingFactoryMethod方法
![](https://img.haomeiwen.com/i23353704/4c4de0fcfae27ca4.png)
全部的逻辑都在这个方法中 : instantiateUsingFactoryMethod。
1.1 是否配置了factory-bean
首先关注下三个 局部变量:
- factoryBean : FactoryBean属性对应的实例。
- factoryClass : 要么是FactoryBean的Class,如果没配置factory-bean就是当前实例化的bean自己的class
- isStatic : factoryMethod 是否是静态的。配置了factory-bean就为false,要求factoryMethod为非静态的,否则, 就必须是静态的(因为没配置factoryBean 那么factoryClass就是当前实例化的bean的class, 只有静态的才能直接调用,非静态的需要实例化之后才能调用, 而当前 正处在实例化阶段, 就会导致永远无法实例化。)
![](https://img.haomeiwen.com/i23353704/b9826d8a99693325.png)
1.1.1 配置了factory-bean
- factoryBean 就直接根据配置的factoryBeanName 从 beanFactory 直接get, 如果这个factoryBean没有实例化,就会提前触发实例化。
- factoryClass 为 factoryBean的class
- isStatic 为false
![](https://img.haomeiwen.com/i23353704/1617389362e69f07.png)
1.1.2 没配置factory-bean
- factoryBean 为null
- factoryClass 为当前实例化的bean自己的class
- isStatic = true
![](https://img.haomeiwen.com/i23353704/1070d156ce7ce0bc.png)
1.2 选择FactoryMethod
-
当配置了Factory-Bean,此时 factoryBean 有值, factoryClass 为 factoryBean的class isStatic 为false
此时获取到的FactoryBean这个对象的类 中 方法名称等于 FactoryMethod的, 且为非 static的 方法对象。
-
当没配置Factory-Bean, 此时factoryBean 为null,factoryClass 为当前实例化的bean自己的class,isStatic = true
那么这个判断 获取到的是 当前正在实例化的bean的 类中,方法名称等于 FactoryMethod的, 且为static的 方法
![](https://img.haomeiwen.com/i23353704/7e3857feae9b8b36.png)
1.3 FactoryMethod只存在一个,直接反射调用
当只获取到一个FactoryMethod,并且是无参的,这时候, 就直接反射调用了。
![](https://img.haomeiwen.com/i23353704/c1ea0176c49452d5.png)
获取到方法之后, 剩下的就是 反射调用
![](https://img.haomeiwen.com/i23353704/d558b8584d650d93.png)
![](https://img.haomeiwen.com/i23353704/83a068054954ebbc.png)
这里, factoryMethod.invoke(factoryBean, args),如果是静态方法,factoryBean传进来是没有值的。如果是非静态方法,那么 factoryBean是有值的。正好。
1.4 FactoryMethod 存在多个的反射调用。
除了无参的 FactoryMethod 之外, 还可能有重写的带有不同参数列表的 多个 同名的 FactoryMethod列表。
此时, 就不会走 FactoryMethod 只存在一个 的 代码分支。不会直接反射,还要经过方法的筛选:
优先选 参数列表最长,并且 参数都可以获取到的那一个
1.4.1 首先按照FactoryMethod 的参数多少 排序,多的排在前面。
![](https://img.haomeiwen.com/i23353704/970277a96279fc69.png)
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();
}
}
![](https://img.haomeiwen.com/i23353704/751b8a81a4afdb7f.png)
1.4.3 反射调用 最合适的方法
![](https://img.haomeiwen.com/i23353704/69d8f170d4796962.png)
最终一个bean就通过这种方式创建好并返回出去了。
网友评论