宏观上看Spring创建对象的过程

对于对象而言,可以分为简单对象复杂对象

  • 简单对象

    简单对象指可以直接new的对象;
    Spring在创建这些对象时,是基于反射来完成的。
  • 复杂对象

    复杂对象指不能直接new的对象。
    比如:要得到接口类型的对象,是不能直接new的,需要使用其实现类来创建。但是有的其实现类也是不能直接new的,比如Connection对象。
    对于这种对象,可以使用实现FactoryBean接口的方式来创建;
    需要实现三个方法:
    getObject() ------> 书写位置 -----> Spring工厂 回调 getObject()获得对象
    getObjectType()
    isSingleton()
    也可以使用静态工厂或者实例工厂来创建;
    静态工厂:
    MyFactory{
    public static Object getObject(){
    xxxx
    xxxxx
    } }
    <bean id="" class="xxx.MyFactory" factory-method="getObject"/> 实例工厂:
    MyFactory{
    public Object getObject(){}
    } <bean id="myFactory" class="xxx.MyFactory"/> <bean id="product" factory-bean="myFactory" factory-method="getObject"/>

    这仅仅完成了对象的创建。我们还要考虑为对象属性进行赋值(也称为属性的注入)。

Spring为创建的对象注入属性

注入的方式:

  • set注入

    <bean id="u" class="">
    <property > ----------set注入
    </bean>

    会有两种注入的形式

    • 程序员自己完成的注入

      可以注入8种基本类型、自建类型(通过ref=)的bean;

    • Spring容器自己的注入(aware)

      实现BeanNameAware接口,实现void setBeanName(String name)方法,Spring容器自动调用它【谁调用谁就会传参】,可以获取当前对象在工厂中的id(beanName),定义一个变量把它存起来就可以了;
      实现BeanFactoryAware接口,实现void setBeanFactory(BeanFactory beanFactory)方法,Spring容器自动调用它,可以获取创建当前对象的工厂对象,定义一个变量把它存起来就可以了。
      BeanFactoryAware接口的应用场景:
      可以解决scope=prototype在注入过程中失效的问题。 比如类A是单例的,类B是多例的,类A中有类B的成员变量b,如果用set注入,每一次获取都是一样的地址,因为类A对象已经被创建出来,并存储到容器里了,再获取成员变量b时,没有为其重新赋值。
      我们可以获取到工厂,每次在a中使用b时,都从容器中获取一次。
      scope=prototype在注入过程中失效的解决方式还有一个,lookup-method = ,但是用的少

      这两种方式先后顺序是怎样的呢?——用户自己设置的set注入在前,容器的注入在后。

  • 构造注入

    <bean id="u" class="">
    <constructor-arg >——————构造注入
    </bean>
  • autowire自动注入

    如果在beans配置,beans管理的所有bean都会自动注入

    如果在bean配置,此bean的属性会自动注入;

工厂创建对象的完整流程

  1. Spring工厂创建对象;
  2. 对属性进行set注入(用户的set注入在前,实现Aware接口容器的set注入在后);
  3. set注入完成后得到的对象交给BeanPostProcessor中的postProcessBeforeInitialization(Object bean, String beanName)方法为对象进行加工(参数bean就是待加工的bean,返回值为加工好的bean);
  4. 为postProcessBeforeInitialization方法加工后的对象进行初始化,有两种方式: 第一种方式实现InitializingBean接口(在前)、第二种方式 指定init-method方法(在后);
  5. 初始化后的对象,交给BeanPostProcessor中的postProcessAfterInitialization(Object bean, String beanName)方法为对象进行加工(参数bean就是待加工的bean,返回值为加工好的bean);
  6. 最后得到加工好的对象,用户可以进行使用;
  7. 工厂调用destroySingletons()方法,工厂关闭,销毁对象。

问题:为什么还需要实现BeanPostProcessor接口为其增加功能,不能在创建对象时,直接写好呢?

答案:BeanPostProcessor接口中的方法,可以为多个对象增加功能,代码可以复用,减少代码的冗余;

加功能是可有可无的功能,如果需要可以加上,如果不需要就取消掉,可以解决代码的耦合。

问题:一般在BeanPostProcessor接口的哪个方法为对象增加功能呢?

答案:postProcessAfterInitialization方法,因为前面已经初始化完成了,后续没有在对bean的操作了;如果在postProcessBeforeInitialization中为对象进行加工,后续可能还会改。

注意:BeanPostProcessor的功能,只有在高级的工厂(比如ApplicationContext)才有。

注意:第5步的初始化操作,和BeanPostProcessor的方法,在开发中我们一般不用。

Spring BeanFactory源码中是如何创建对象的

BeanFactory beanFactory = new XmlBeanFactory(new ClassPathResource(""));
beanFactory.getBean("id");

第一行代码的作用:

读取xml文件,解析bean标签,封装成BeanDefinition对象,并以id为key,BeanDefinition对象为value存储到map中;

第二行代码的作用:

1.基于BeanDefinition创建对象;
2.创建对象的过程,包括前文生命周期中除销毁的步骤;
3.创建对象的过程中,需要按照scope进行讨论:
scope=singleton——单例对象,Spring中使用map结构(key为bean的id,value为bean)来保证永远只创建一次;
scope=prototype——每次都走一遍创建对象的流程。

宏观上看Spring创建对象的过程的更多相关文章

  1. ArcObjects SDK开发 003 宏观角度看ArcObjects SDK

    1.为什么要宏观上看ArcObjects SDK ArcObjects SDK库是一个非常庞大复杂COM组件集合,ArcGIS10.0有1000多个枚举.90多个结构体.5000多个接口以及4000多 ...

  2. Spring源码分析(一):从哪里开始看spring源码(系列文章基于Spring5.0)

    概述 对于大多数第一次看spring源码的人来说,都会感觉不知从哪开始看起,因为spring项目源码由多个子项目组成,如spring-beans,spring-context,spring-core, ...

  3. 从启动日志看Spring IOC的初始化和Bean生命周期

    一.Tomcat中启动IoC容器的日志 启动Tomcat等容器时,控制台每次都打印出一些日志. 最近刚好在研究Spring源码,所以换个角度,从启动日志来简单的看看Spring的初始化过程! 以下是T ...

  4. Spring Boot启动过程(四):Spring Boot内嵌Tomcat启动

    之前在Spring Boot启动过程(二)提到过createEmbeddedServletContainer创建了内嵌的Servlet容器,我用的是默认的Tomcat. private void cr ...

  5. Spring Boot启动过程(七):Connector初始化

    Connector实例的创建已经在Spring Boot启动过程(四):Spring Boot内嵌Tomcat启动中提到了: Connector是LifecycleMBeanBase的子类,先是设置L ...

  6. 由一次报错引发的对于Spring创建对象的理解

    org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'ent ...

  7. Spring Boot启动过程及回调接口汇总

    Spring Boot启动过程及回调接口汇总 链接: https://www.itcodemonkey.com/article/1431.html 来自:chanjarster (Daniel Qia ...

  8. 【SpringMVC学习01】宏观上把握SpringMVC框架

    springmvc是一个基于mvc的web框架,是spring框架的一个模块,所以springmvc和spring无需通过中间整合层进行整合.我们先来看下spring的一个架构模型,看springmv ...

  9. 站在巨人的肩膀上看Servlet——原来如此(更适合初学者认识Servlet)

    前言: 有段时间没更新博客了,这段时间因为要准备考试,考完试后又忙了一阵别的事,一直没能静下心来写博客.大学考试真是越来越恶心了,各种心酸,那酸爽,够味.不过还好,马上就要大三了,听大三学长学姐说大三 ...

  10. spring MVC 运行过程

    以Tomcat为例,想在Web容器中使用Spirng MVC,必须进行四项的配置: 1.修改web.xml, 2.添加servlet定义.编写servletname-servlet.xml( serv ...

随机推荐

  1. A/B测试有哪些常见应用场景?——火山引擎DataTester科普

      更多技术交流.求职机会,欢迎关注字节跳动数据平台微信公众号,回复[1]进入官方交流群 火山引擎 DataTester不仅对外提供服务,也是字节跳动内部所应用的A/B实验平台,它基于先进的底层算法, ...

  2. 火山引擎云原生数据仓库 ByteHouse 技术白皮书 V1.0 (Ⅳ)

    更多技术交流.求职机会,欢迎关注字节跳动数据平台微信公众号,回复[1]进入官方交流群 近日,<火山引擎云原生数据仓库 ByteHouse 技术白皮书>正式发布.白皮书简述了 ByteHou ...

  3. ByteHouse:基于ClickHouse的实时数仓能力升级解读

     更多技术交流.求职机会,欢迎关注字节跳动数据平台微信公众号,回复[1]进入官方交流群   ByteHouse是火山引擎上的一款云原生数据仓库,为用户带来极速分析体验,能够支撑实时数据分析和海量数据离 ...

  4. MongoDB 客户端工具,Studio3T 无法启动

    阿里云 MongoDB 创建库添加用户并授权 MongoDB 客户端工具,Studio3T 无法启动,原因可能是因为本地的 java 版本导致 C:\Users\cj218>java -vers ...

  5. PS 独立集中标识下修改项目采购类型增强

    1.当物料独立集中标识为2,采购类型通过BAPI:BAPI_NETWORK_COMP_ADD,type_of_pur_resv传入'7',则报错"组件分配并不是未销售订单或项目库存而设的&q ...

  6. JavaScript到底应不应该加分号?JavaScript自动插入分号规则详解

    JavaScript 提供了 automatic semicolon insertion (ASI)自动插入分号规则,在不加分号的情况下,会自动补充分号来分隔不同语句. 导致在继左大括号换行.tab ...

  7. 版本升级 | v1.0.13发布,传下去:更好用了

    新发行版来啦~ 本次更新主要聚焦兼容性的提升及结果报告格式的增加,另外对部分解析逻辑及使用体验进行了优化.在这里特别鸣谢大佬@Hugo-X在社区仓库提交的PR~ 后续,OpenSCA项目组会继续致力于 ...

  8. mybatis plus 主键策略

    博主原创,转载请注明出处: mybatis plus 对实体类映射表的主键做了注解支持,该注解为 @TableId ,如果不使用该注解,mybatis plus 默认主键生成的策略是内部封装的雪花算法 ...

  9. 26-IP调用 - PLL

    1.PLL IP核简介 PLL(Phaze Locked Loop)锁相环是最常用的IP核之一,其性能强大,可以对输入到FPGA的时钟信号进行任意的分频.倍频.相位调整.占空比调整,从而输出一个期望时 ...

  10. 【面试题精讲】如何使用Stream的聚合功能

    有的时候博客内容会有变动,首发博客是最新的,其他博客地址可能会未同步,认准https://blog.zysicyj.top 首发博客地址 系列文章地址 求和(Sum): List<Integer ...