likes
comments
collection
share

【保姆级】Spring创建对象——今天是factory-method专场!~

作者站长头像
站长
· 阅读数 34

这个步骤在createBeanInstance()方法中有使用,我们先来看下这个方法中都干了些啥(。・ω・。)ノ

首先,方法开头确认了beanClass是否被加载(因为只有被加载叻的对象才是可以实例化的)

【保姆级】Spring创建对象——今天是factory-method专场!~

然后,判断当前beanDefinition中是否包含实例供应器,此步骤如果instanceSupplier!=null的话,则会直接通过obtainFromSupplier(instanceSupplier, beanName);方法直接返回一个Bean的包装类BeanWrapper而不会再进行下面的逻辑叻(保姆级测试教程戳戳【保姆级】Spring创建对象——今天是Supplier专场!

【保姆级】Spring创建对象——今天是factory-method专场!~

所以只有在不满足这一条判断的前提下,才会进入我们今天要分析的使用factory-method创建对象

【保姆级】Spring创建对象——今天是factory-method专场!~

来~开始٩(˃̶͈̀௰˂̶͈́)و

首先,需要啰嗦下通过工厂模式创建实例对象主要有两种方式:

  • 静态工厂(无需工厂的实例对象)
  • 实例工厂(需要创建工厂的实例对象)

所以本案例中我们创建了两个工厂类(静态工厂类:StudentStaticFactory.java和实例工厂类:StudentInstanceFactory.java

创建文件

Student.java

【保姆级】Spring创建对象——今天是factory-method专场!~

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

【保姆级】Spring创建对象——今天是factory-method专场!~

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

【保姆级】Spring创建对象——今天是factory-method专场!~

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配置文件

【保姆级】Spring创建对象——今天是factory-method专场!~

 <?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":为方法指定参数

测试类

【保姆级】Spring创建对象——今天是factory-method专场!~

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 ()) ;
   }
} 

测试结果

【保姆级】Spring创建对象——今天是factory-method专场!~

Debug分析

在使用工厂方法初始化策略的位置打个断点,如下图

【保姆级】Spring创建对象——今天是factory-method专场!~

默认情况(在未创建案例中的文件时),会发现mbd.getFactoryMethodName()=null,不会进入if的逻辑中

【保姆级】Spring创建对象——今天是factory-method专场!~

当执行案例中的测试方法

【保姆级】Spring创建对象——今天是factory-method专场!~

会发现,此时mbd.getFactoryMethodName()="getStudent",所以我们进入了if的逻辑中(*≧ω≦)

点击进入,进入instantiateUsingFactoryMethod()方法中(这里先捋下执行逻辑,文章【Spring源码】22. factory-method创建对象关键函数详解:instantiateUsingFactoryMethod()中对这个方法做了详细介绍,毕竟行数300+的方法,值得单独拎出来瞅瞅(˶‾᷄ ⁻̫ ‾᷅˵)),instantiateUsingFactoryMethod()方法是通过一个命名的工厂方法来实例化Bean的,会返回一个Bean的包装类BeanWrapper

【保姆级】Spring创建对象——今天是factory-method专场!~

然后就不会再向下继续,而会直接回到createBeanInstance()方法中,继续后面的包装以及初始化的逻辑

【保姆级】Spring创建对象——今天是factory-method专场!~

我们下次继续┏ (^ω^)=撒个花🎉🎉🎉

转载自:https://juejin.cn/post/7137606986728177671
评论
请登录