码农知识堂 - 1000bd
  •   Python
  •   PHP
  •   JS/TS
  •   JAVA
  •   C/C++
  •   C#
  •   GO
  •   Kotlin
  •   Swift
  • 【保姆级·创建对象】如何通过factory-method创建对象


    【Spring源码系列- IOC】

    1

    【Spring源码】0.安装Gradle环境

    2

    【Spring源码】1.下载与编译_pom relocation to an other version number is not f

    3

    【Spring源码】2.试个水先~Debug找到传说中的三级缓存(图解向,堆图预警)

    4

    【Spring源码】3. xml文件如何转换成BeanDefinition(主要涉及prepareRefresh()+ obtainFreshBeanFactory()两个函数,图解向,堆图预警)_spring xml转bean

    5

    【Spring源码】4. 自己搞个标签?~自定义标签保姆级全过程(图解向,堆图预警)

    6

    【Spring源码】5.spring的bean工厂准备工作(prepareBeanFactory(beanFactory)

    7

    【Spring源码】6. Spring扩展自定义属性编辑器保姆级教程

    8

    【Spring源码】7. 如何添加自定义的BeanFactoryPostProcessor

    9

    【Spring源码】8. 捋下invokeBeanFactoryPostProcessors()主要处理流程

    10

    【Spring源码】9. 超级重要的ConfigurationClassPostProcessor

    11

    【Spring源码】10. 递归调用的processConfigurationClass()方法

    12

    【Spring源码】11. 我是注解类不?checkConfigurationClassCandidate()注解类判断方法详解

    13

    【Spring源码】12. 注册bean处理器registerBeanPostProcessors()

    14

    【Spring源码】13. 国际化处理initMessageSource()源码解析

    【补充内容】【保姆级】SpringBoot项目中的i18n国际化

    15

    【Spring源码】14. 消息多播器(观察者模式)

    【补充内容】【保姆级示例向】观察者模式

    16

    【Spring源码】15. Bean的创建过程(1.概述篇)

    17

    【Spring源码】16. Bean的创建过程(2)

    18

    【Spring源码】17.创建Bean这篇认真的@(・●・)@

    【补充内容】

    【保姆级·创建对象】如何通过Supplier创建对象

    【保姆级·创建对象】如何通过factory-method创建对象

    【保姆级·创建对象】如何利用resolveBeforeInstantiation()在预处理阶段返回一个Bean的实例对象

    19

    【Spring源码】18. factory-method创建对象关键函数详解:instantiateUsingFactoryMethod()

    20

    【Spring源码】19. 没合适的构造器?找determineCandidateConstructors()!

    21

    【Spring源码】20. MergedBeanDefinitionPostProcessor修改/合并bean定义

    【补充内容】

    【保姆级】@PostConstruct & @PreDestroy使用示例

    【Spring源码】AutowiredAnnotationBeanPostProcessor.postProcessMergedBeanDefinition()详解

    【Spring源码】CommonAnnotationBeanPostProcessor.postProcessMergedBeanDefinition()详解

    22

    【Spring源码】21. 初探循环依赖

    【补充内容】

    【保姆级】手把手Debug循环依赖的整体流程

    【实践向】当移除了三级缓存……

    【分析向】没有三级缓存会导致什么?

    【Spring源码】插播一个创建代理对象的wrapIfNecessary()方法

    23

    【Spring源码】22. 属性填充populateBean()详解

    【补充内容】

    【Spring源码】自动注入·名称:autowireByName()详解

    【Spring源码】自动注入·类型:autowireByType()详解

    【Spring源码】属性值的解析与赋值:populateBean().applyPropertyValues()

    【保姆级】超超超简单的自定义注解实现@Autowired同款功能

    24

    【Spring源码】23. 执行初始化逻辑:initializeBean()

    本文目录

    创建文件

    Student.java

    StudentStaticFactory.java

    ​StudentInstanceFactory.java

    xml配置文件

    测试类

    测试结果

    Debug分析


    这个步骤在createBeanInstance()方法中有使用,我们先来看下这个方法中都干了些啥(。・ω・。)ノ 首先,方法开头确认了beanClass是否被加载(因为只有被加载叻的对象才是可以实例化的)

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

    【保姆级·创建对象】如何通过Supplier创建对象_AQin1012的博客-CSDN博客

    )

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

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

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

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

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

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

    创建文件

    Student.java

    1. public class Student {
    2. private String name;
    3. private Integer age;
    4. public String getName() {
    5. return name;
    6. }
    7. public void setName(String name) {
    8. this.name = name;
    9. }
    10. public Integer getAge() {
    11. return age;
    12. }
    13. public void setAge(Integer age) {
    14. this.age = age;
    15. }
    16. }

    StudentStaticFactory.java

    1. public class StudentStaticFactory {
    2. public static Student getStudent(String name) {
    3. Student student = new Student();
    4. student.setName(name);
    5. student.setAge(88);
    6. return student;
    7. }
    8. }

    ​StudentInstanceFactory.java

    1. public class StudentInstanceFactory {
    2. public Student getStudent(String name) {
    3. Student student = new Student();
    4. student.setName(name);
    5. student.setAge(88);
    6. return student;
    7. }
    8. }

    xml配置文件

    1. "1.0" encoding="UTF-8"?>
    2. <beans xmlns="http://www.springframework.org/schema/beans"
    3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    4. xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    5. <bean id="student" class="com.aqin.custom.factoryMethod.StudentStaticFactory" factory-method="getStudent">
    6. <constructor-arg value="aqin">constructor-arg>
    7. bean>
    8. <bean id="studentInstanceFactory" class="com.aqin.custom.factoryMethod.StudentInstanceFactory">bean>
    9. <bean id="student2" class="com.aqin.custom.factoryMethod.Student" factory-bean="studentInstanceFactory"
    10. factory-method="getStudent">
    11. <constructor-arg value="aqin2">constructor-arg>
    12. bean>
    13. beans>

    ​参数说明

    • factory-bean="personStaticFactory":指定使用的工厂实例是"personStaticFactory"

    • factory-method="getStudent":指定使用的工厂实例的方法为"getStudent"

    • constructor-arg value="aqin":为方法指定参数

    测试类

    1. public class TestFactoryMethod {
    2. public static void main(String[] args) {
    3. ApplicationContext applicationContext = new ClassPathXmlApplicationContext("factoryMethod.xml");
    4. Student bean = applicationContext.getBean("student", Student.class);
    5. System.out.println(bean.getName());
    6. System.out.println("-------------------------------");
    7. Student bean2 = applicationContext.getBean("student2", Student.class);
    8. System.out.println(bean2.getName());
    9. }
    10. }

    测试结果

    Debug分析

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

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

    ​当执行案例中的测试方法

    会发现,此时mbd.getFactoryMethodName()="getStudent",所以我们进入了if的逻辑中(*≧ω≦) 点击进入,进入instantiateUsingFactoryMethod()方法中(这里先捋下执行逻辑,后续会对这个方法做详细介绍,毕竟行数300+的方法,值得单独拎出来瞅瞅(˶‾᷄ ⁻̫ ‾᷅˵)),instantiateUsingFactoryMethod()方法是通过一个命名的工厂方法来实例化Bean的,会返回一个Bean的包装类BeanWrapper

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

  • 相关阅读:
    C语言—窄字符或宽字符
    Android 10.0 Launcher 启动流程
    新生儿黄疸:原因、科普和注意事项
    Delete `␍`eslintprettier/prettier
    JS-函数
    6-7抽象的应用场景
    5个优秀设计网站,素材、灵感一步到位。
    LeetCode --- 1365. How Many Numbers Are Smaller Than the Current Number 解题报告
    java毕业生设计-学生考勤管理系统-计算机源码+系统+mysql+调试部署+lw
    名单揭晓 | 2021年度中国杰出知识产权服务团队
  • 原文地址:https://blog.csdn.net/aqin1012/article/details/128204883
  • 最新文章
  • 沪漂五周年了:我越来越迷茫了
    Agentic Skill Routing 实战:别再把所有 Skill 塞进 AI Agent 上下文
    MySQL-Seconds_behind_master的精度误差
    [MAF预定义ChatClient中间件-03]CachingChatClient——利用缓存省钱省时间
    AI的至暗历史:从万众期待到被政府撤资,AI的两次死亡徘徊
    Agent OS :五种驯服不确定性的范式
    PortSwigger SQL注入LAB11
    数据库即时编译JIT
    [Begin]AI Learn Data Day 0
    深度学习进阶(二十七)现代 LLM 的核心架构设计其二:SwiGLU
  • 热门文章
  • 十款代码表白小特效 一个比一个浪漫 赶紧收藏起来吧!!!
    奉劝各位学弟学妹们,该打造你的技术影响力了!
    五年了,我在 CSDN 的两个一百万。
    Java俄罗斯方块,老程序员花了一个周末,连接中学年代!
    面试官都震惊,你这网络基础可以啊!
    你真的会用百度吗?我不信 — 那些不为人知的搜索引擎语法
    心情不好的时候,用 Python 画棵樱花树送给自己吧
    通宵一晚做出来的一款类似CS的第一人称射击游戏Demo!原来做游戏也不是很难,连憨憨学妹都学会了!
    13 万字 C 语言从入门到精通保姆级教程2021 年版
    10行代码集2000张美女图,Python爬虫120例,再上征途
小工具 小游戏
Copyright © 2022 侵权请联系2656653265@qq.com    京ICP备2022015340号-1

京公网安备 11010502049817号