Spring构造函数

一、分析说明

Spring中的一个Bean,需要实例化得到一个对象,而实例化就需要用到构造方法。那么下面来用各种各样的现象来进行说明:

2.1、一个构造函数

一般情况下,一个类只有一个构造方法:

  1. 要么是无参的构造方法
  2. 要么是有参的构造方法

如果只有一个构造方法,那么实例化就只能使用这个构造方法了。

java版本

只能选择第三个。

xml配置版

也是只能用第三个。

2.2、多个构造函数

上面是只有一个构造方法的情况,那么如果有多个构造方法呢?

又分为两种情况多个构造方法中存不存在无参的构造方法。

  1. 如果开发者指定了想要使用的构造方法,那么就用这个构造方法;
  2. 如果开发者没有指定想要使用的构造方法,则看开发者有没有让Spring自动去选择构造方法;
  3. 如果开发者也没有让Spring自动去选择构造方法,则Spring利用无参构造方法,如果没有无参构造方法,则报错;

1、针对第一点,开发者可以通过什么方式来指定使用哪个构造方法呢?

  1. xml中的标签,这个标签表示构造方法参数,所以可以根据这个确定想要使用的构造方法的参数个数,从而确定想要使用的构造方法
  2. 通过@Autowired注解,@Autowired注解可以写在构造方法上,所以哪个构造方法上写了@Autowired注解,表示开发者想使用哪个构造方法,当然,它和第一个方式的不同点是,通过xml的方式,我们直接指定了构造方法的参数值,而通过@Autowired注解的方式,需要Spring通过byType+byName的方式去找到符合条件的bean作为构造方法的参数值
当然,还有一种情况,就是多个构造方法上写了@Autowired注解,那么此时Spring会报错。 但是,因为@Autowired还有一个属性required,默认为ture,所以一个类中,只有能一个构造方法标注了@Autowired或@Autowired(required=true),有多个会报错。但是可以有多个@Autowired(required=false),这种情况下,需要Spring从这些构造方法中去自动选择一个构造方法。

2、再来看第二点,如果开发者没有指定想要使用的构造方法,则看开发者有没有让Spring自动去选择构造方法,对于这一点,只能用在ClassPathXmlApplicationContext,因为通过AnnotationConfigApplicationContext没有办法去指定某个bean可以自动去选择构造方法,而通过

ClassPathXmlApplicationContext可以在xml中指定某个bean的autowire为constructor,虽然这个属性表示通过构造方法自动注入,所以需要自动的去选择一个构造方法进行自动注入,因为是构造方法,所以顺便是进行实例化

针对上面的第二点,通常我们不会使用xml的方式来进行创建,所以我们选择java代码来进行对应的配置:

对应的类:

容器注册:

如果这么来使用的话,那么是会报错的!!!!

因为spring不知道要找哪个构造方法,想要去找默认的构造方法来进行实例化。

所以要告知spring要通过哪个构造方法来进行选择进行实例化。那么只要添加上一行代码即可:

可以看到spring会选择最多的构造方法来进行注入,是可以来进行注入的。

源码思路

  1. AbstractAutowireCapableBeanFactory类中的createBeanInstance()方法会去创建一个Bean实例
  2. 根据BeanDefinition加载类得到Class对象
  3. 如果BeanDefinition绑定了一个Supplier,那就调用Supplier的get方法得到一个对象并直接返回
  4. 如果BeanDefinition中存在factoryMethodName,那么就调用该工厂方法得到一个bean对象并返回
  5. 如果BeanDefinition已经自动构造过了,那就调用autowireConstructor()自动构造一个对象
  6. 调用SmartInstantiationAwareBeanPostProcessor的determineCandidateConstructors()方法得到哪些构造方法是可以用的
  7. 如果存在可用得构造方法,或者当前BeanDefinition的autowired是AUTOWIRE_CONSTRUCTOR,或者BeanDefinition中指定了构造方法参数值,或者创建Bean的时候指定了构造方法参数值,那么就调用autowireConstructor()方法自动构造一个对象
  8. 最后,如果不是上述情况,就根据无参的构造方法实例化一个对象

为什么分越少优先级越高?

主要是计算找到的bean和构造方法参数类型匹配程度有多高。

假设bean的类型为A,A的父类是B,B的父类是C,同时A实现了接口D

如果构造方法的参数类型为A,那么完全匹配,得分为0

如果构造方法的参数类型为B,那么得分为2

如果构造方法的参数类型为C,那么得分为4

如果构造方法的参数类型为D,那么得分为1

可以直接使用如下代码进行测试:

Object[] objects = new Object[]{new A()};

// 0
System.out.println(MethodInvoker.getTypeDifferenceWeight(new Class[]{A.class}, objects)); // 2
System.out.println(MethodInvoker.getTypeDifferenceWeight(new Class[]{B.class}, objects)); // 4
System.out.println(MethodInvoker.getTypeDifferenceWeight(new Class[]{C.class}, objects)); // 1
System.out.println(MethodInvoker.getTypeDifferenceWeight(new Class[]{D.class}, objects));

所以,我们可以发现,越匹配分数越低。

流程分析

Spring构造函数的更多相关文章

  1. spring构造函数注入、setter方法注入和接口注入

    Spring开发指南中所说的三种注入方式: Type1 接口注入 我们常常借助接口来将调用者与实现者分离.如: public class ClassA { private InterfaceB clz ...

  2. Spring源码学习-容器BeanFactory(三) BeanDefinition的创建-解析Spring的默认标签

    写在前面 上文Spring源码学习-容器BeanFactory(二) BeanDefinition的创建-解析前BeanDefinition的前置操作中Spring对XML解析后创建了对应的Docum ...

  3. Spring 系列教程之默认标签的解析

    Spring 系列教程之默认标签的解析 之前提到过 Spring 中的标签包括默认标签和自定义标签两种,而两种标签的用法以及解析方式存在着很大的不同,本章节重点带领读者详细分析默认标签的解析过程. 默 ...

  4. Spring源码分析(七)bean标签的解析及注册

    摘要:本文结合<Spring源码深度解析>来分析Spring 5.0.6版本的源代码.若有描述错误之处,欢迎指正. 在上一篇中提到过Spring中的标签包括默认标签和自定义标签两种,而两种 ...

  5. Spring和依赖注入的价值

    javaeye上看到有帖子,置疑spring和依赖注入的价值,回复内容整理如下: 依赖注入对设计有利,而spring则促进了依赖注入的使用. 如果业务处理类,它所使用的倚赖,都是依靠在这个类内部实现或 ...

  6. 从架构师视角看是否该用Kotlin做服务端开发?

    前言 自从Oracle收购Sun之后,对Java收费或加强控制的尝试从未间断,谷歌与Oracle围绕Java API的官司也跌宕起伏.虽然Oracle只是针对Oracle JDK8的升级收费,并释放了 ...

  7. 极简SpringBoot指南-Chapter02-Spring依赖注入的方式

    仓库地址 w4ngzhen/springboot-simple-guide: This is a project that guides SpringBoot users to get started ...

  8. 关于Spring的构造函数,init-method,和依赖注入的先后顺序

    接触学习Spring一段时间了,今天突然脑子短路,竟然一时间忘记了构造函数,init-method,和依赖注入的先后顺序,然后打开IDE去验证后.构造函数-->依赖注入-->init-me ...

  9. spring 自动扫描、注册的类是否可以定义构造函数

    答案是肯定的. 方法如下: @Service public class SimpleMovieLister { private MovieFinder movieFinder; @Autowired ...

  10. (spring-第3回【IoC基础篇】)spring的依赖注入-属性、构造函数、工厂方法等的注入(基于XML)

    Spring要把xml配置中bean的属性实例化为具体的bean,"依赖注入"是关卡.所谓的"依赖注入",就是把应用程序对bean的属性依赖都注入到spring ...

随机推荐

  1. k8s驱逐篇(5)-kube-controller-manager驱逐

    kube-controller-manager驱逐 概述 kube-controller-manager驱逐主要依靠NodeLifecycleController以及其中的TaintManager: ...

  2. 前端入门 HTTP协议 HTML简介 head内常见标签 body内常见标签 特殊符号 列表标签 表格标签 表单标签

    目录 前端和后端的概念 前端前戏之B/S架构 数据交互的协议 HTTP协议 1.四大特性 1. 基于请求响应 2. 基于TCP.IP作用与应用层之上的协议 3. 无状态 4. 无\短连接 2.数据格式 ...

  3. MYSQL下载 环境配置 修改密码 基本SQL语句

    目录 存取数据的演变史 数据库软件应用史 数据库的本质 数据库的分类 关系型数据库 特征 常见关系型数据库 非关系型数据库 特征 常见非关系型数据库 mysql简介 mysql下载 启动mysql 系 ...

  4. Nmap常用方法

    1.扫描单个目标地址  在Nmap后面直接添加目标地址即可扫描  nmap 目标地址  2.扫描多个目标地址  如果目标不在同一网段,或在同一网段但不连续且数量不多,可以使用该方法进行扫描  nmap ...

  5. 一篇文章带你了解设计模式原理——UML图和软件设计原则

    一篇文章带你了解设计模式原理--UML图和软件设计原则 我们在学习过程中可能并不会关心设计模式,但一旦牵扯到项目和面试,设计模式就成了我们的短板 这篇文章并不会讲到二十三种设计模式,但是会讲解设计模式 ...

  6. MongoDB - 分片简介

    简介 什么是分片 高数据量和高吞吐量的数据库应用会对单机的性能造成较大压力,大的查询会将单机的 CPU 耗尽,大的数据量对单机的存储压力较大,最终会耗尽系统的内存压力转移到磁盘 IO 上. 为了解决这 ...

  7. CVE-2016-4437

    漏洞名称 Apache shiro 1.2.4反序列化漏洞(CVE-2016-4437) 利用条件 Apache Shiro <= 1.2.4 漏洞原理 Shiro提供了记住我(Remember ...

  8. 聊聊web漏洞挖掘第一期

    之前写2022年度总结的时候,有提到要给大家分享漏洞挖掘技巧.这里简单分享一些思路,更多的内容需要大家举一反三. 文章准备昨晚写的,昨天晚上出去唱歌,回来太晚了,耽搁了.昨天是我工作的last day ...

  9. LIS求解(包括优化)

    首先,让我来看看LIS问题 Description 一个数的序列 bi,当 b1 < b2 < ... < bS 的时候,我们称这个序列是上升的.对于给定的一个序列(a1,a2,.. ...

  10. prettier+ts+eslint+vscode配置代码保存自动格式化,自动remove unsed declaration,delete no-unused-imports

    每天都要开心(▽)哇: 以这个项目为案例 下面是项目的基本情况 What would you like to build? › App with Quasar CLI, let's go! Proje ...