【保姆级】Spring创建对象——今天是factory-method专场!~
这个步骤在createBeanInstance()
方法中有使用,我们先来看下这个方法中都干了些啥(。・ω・。)ノ
首先,方法开头确认了beanClass
是否被加载(因为只有被加载叻的对象才是可以实例化的)
然后,判断当前beanDefinition
中是否包含实例供应器,此步骤如果instanceSupplier!=null
的话,则会直接通过obtainFromSupplier(instanceSupplier, beanName);
方法直接返回一个Bean
的包装类BeanWrapper
而不会再进行下面的逻辑叻(保姆级测试教程戳戳【保姆级】Spring创建对象——今天是Supplier专场!)
所以只有在不满足这一条判断的前提下,才会进入我们今天要分析的使用factory-method
创建对象
来~开始٩(˃̶͈̀௰˂̶͈́)و
首先,需要啰嗦下通过工厂模式创建实例对象主要有两种方式:
- 静态工厂(无需工厂的实例对象)
- 实例工厂(需要创建工厂的实例对象)
所以本案例中我们创建了两个工厂类(静态工厂类:StudentStaticFactory.java
和实例工厂类:StudentInstanceFactory.java
)
创建文件
Student.java
package com.aqin.custom.factoryMethod;
/**
* @Description
* @Author aqin1012 AQin.
* @Date 2022/8/30 1:14 PM
* @Version 1.0
*/
public class Student {
private String name;
private Integer age;
public String getName () {
return name;
}
public void setName ( String name ) {
this.name = name;
}
public Integer getAge () {
return age;
}
public void setAge ( Integer age ) {
this.age = age;
}
}
StudentStaticFactory.java
package com.aqin.custom.factoryMethod;
/**
* @Description
* @Author aqin1012 AQin.
* @Date 2022/8/30 1:18 PM
* @Version 1.0
*/
public class StudentStaticFactory {
public static Student getStudent ( String name ) {
Student student = new Student () ;
student.setName ( name ) ;
student.setAge ( 88 ) ;
return student;
}
}
StudentInstanceFactory.java
package com.aqin.custom.factoryMethod;
/**
* @Description
* @Author aqin1012 AQin.
* @Date 2022/8/30 1:18 PM
* @Version 1.0
*/
public class StudentInstanceFactory {
public Student getStudent ( String name ) {
Student student = new Student () ;
student.setName ( name ) ;
student.setAge ( 88 ) ;
return student;
}
}
xml配置文件
<?xml version= "1.0" encoding= "UTF-8" ?> < beans xmlns = "http://www.springframework.org/schema/beans" xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation = "http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd" > < bean id = "student" class = "com.aqin.custom.factoryMethod.StudentStaticFactory" factory-method = "getStudent" > < constructor-arg value = "aqin" ></ constructor-arg > </ bean > < bean id = "studentInstanceFactory" class = "com.aqin.custom.factoryMethod.StudentInstanceFactory" ></ bean > < bean id = "student2" class = "com.aqin.custom.factoryMethod.Student" factory-bean = "studentInstanceFactory" factory-method = "getStudent" > < constructor-arg value = "aqin2" ></ constructor-arg > </ bean > </ beans >
参数说明
factory-bean="personStaticFactory"
:指定使用的工厂实例是"personStaticFactory"
factory-method="getStudent"
:指定使用的工厂实例的方法为"getStudent"
constructor-arg value="aqin"
:为方法指定参数
测试类
package com.aqin.custom.factoryMethod;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* @Description
* @Author aqin1012 AQin.
* @Date 2022/8/30 1:47 PM
* @Version 1.0
*/
public class TestFactoryMethod {
public static void main ( String [] args ) {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext ( "factoryMethod.xml" ) ;
Student bean = applicationContext.getBean ( "student", Student.class ) ;
System.out.println ( bean.getName ()) ;
System.out.println ( "-------------------------------" ) ;
Student bean2 = applicationContext.getBean ( "student2", Student.class ) ;
System.out.println ( bean2.getName ()) ;
}
}
测试结果
Debug分析
在使用工厂方法初始化策略的位置打个断点,如下图
默认情况(在未创建案例中的文件时),会发现mbd.getFactoryMethodName()=null
,不会进入if
的逻辑中
当执行案例中的测试方法
会发现,此时mbd.getFactoryMethodName()="getStudent"
,所以我们进入了if
的逻辑中(*≧ω≦)
点击进入,进入instantiateUsingFactoryMethod()
方法中(这里先捋下执行逻辑,文章【Spring源码】22. factory-method创建对象关键函数详解:instantiateUsingFactoryMethod()中对这个方法做了详细介绍,毕竟行数300+的方法,值得单独拎出来瞅瞅(˶‾᷄ ⁻̫ ‾᷅˵)),instantiateUsingFactoryMethod()
方法是通过一个命名的工厂方法来实例化Bean
的,会返回一个Bean
的包装类BeanWrapper
然后就不会再向下继续,而会直接回到createBeanInstance()
方法中,继续后面的包装以及初始化的逻辑
我们下次继续┏ (^ω^)=撒个花🎉🎉🎉
转载自:https://juejin.cn/post/7137606986728177671