这个步骤在createBeanInstance()方法中有使用,我们先来看下这个方法中都干了些啥(。・ω・。)ノ 首先,方法开头确认了beanClass是否被加载(因为只有被加载叻的对象才是可以实例化的)
然后,判断当前beanDefinition中是否包含实例供应器,此步骤如果instanceSupplier!=null的话,则会直接通过obtainFromSupplier(instanceSupplier, beanName);方法直接返回一个Bean的包装类BeanWrapper而不会再进行下面的逻辑叻(保姆级测试教程戳戳
【保姆级·创建对象】如何通过Supplier创建对象_AQin1012的博客-CSDN博客
)
所以只有在不满足这一条判断的前提下,才会进入我们今天要分析的使用factory-method
创建对象
来~开始٩(˃̶͈̀௰˂̶͈́)و
首先,需要啰嗦下通过工厂模式创建实例对象主要有两种方式:
-
静态工厂(无需工厂的实例对象)
-
实例工厂(需要创建工厂的实例对象)
所以本案例中我们创建了两个工厂类(静态工厂类:StudentStaticFactory.java和实例工厂类:StudentInstanceFactory.java)
创建文件
Student.java
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
public class StudentStaticFactory {
public static Student getStudent(String name) {
Student student = new Student();
student.setName(name);
student.setAge(88);
return student;
}
}
StudentInstanceFactory.java
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":为方法指定参数
测试类
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()方法中(这里先捋下执行逻辑,后续会对这个方法做详细介绍,毕竟行数300+的方法,值得单独拎出来瞅瞅(˶‾᷄ ⁻̫ ‾᷅˵)),instantiateUsingFactoryMethod()方法是通过一个命名的工厂方法来实例化Bean的,会返回一个Bean的包装类BeanWrapper
然后就不会再向下继续,而会直接回到createBeanInstance()方法中,继续后面的包装以及初始化的逻辑