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. Ubuntu20.04更换国内镜像源(阿里、网易163、清华、中科大)

    更换方法 Ubuntu采用apt作为软件安装工具,其镜像源列表记录在/etc/apt/source.list文件中. 首先将source.list复制为source.list.bak备份,然后将sou ...

  2. 【Java】二分查找标准代码

    太菜了..写不出正确的... 干脆放一个标准代码,之后参考 boolean BinarySearch(int[] m){ int l=0,r=m.length-1;//减1相当于数组两头(lr都能指到 ...

  3. angr原理与实践(三)——Arbiter:一种弥合二进制程序漏洞发现中的静态和动态鸿沟

    ​ 转载请说明出处:信安科研人 please subscribe my official wechat :信安科研人 获取更多安全资讯 原文链接:sec22-vadayath.pdf (usenix. ...

  4. JavaScript:对象:如何读取、添加、删除对象的属性?

    如何给对象添加属性? 直接对象名.属性名去添加属性 直接对象名[属性名]去添加属性,此时属性名得是字符串类型,可以直接引号,也可以用变量名 如何读取对象的属性值? 这个操作,和添加属性是一样的,即用点 ...

  5. 开源库libcli的安装与使用

    源码:https://github.com/dparrish/libcli 环境 Ubuntu 20.04.2 LTS 编译libcli 参考:README.md 按照libcli中的 README ...

  6. SQLSERVER 的主键索引真的是物理有序吗?

    一:背景 1. 讲故事 最近在看 SQL SERVER 2008 查询性能优化,书中说当一个表创建了聚集索引,那么表中的行会按照主键索引的顺序物理排列,这里有一个关键词叫:物理排列,如果不了解底层原理 ...

  7. 华为云Stack新版发布:构筑行业云底座,共创行业新价值

    摘要:在以"政企深度用云,释放数字生产力"为主题的华为云Stack战略暨新品发布会上,华为云提出深度用云三大关键举措,并发布华为云Stack 8.2版本,以智能进化推动创造行业新价 ...

  8. 浅谈RMQ问题

    RMQ:question 有一个长度为 N N N的数组,数组中的数是无序的( 1 < = n < = 5 ∗ 1 0 5 1<=n<=5*10^5 1<=n<=5 ...

  9. jupyter的配置

    step1.安装jupyter 使用pip或者conda等包管理工具安装jupyter(这部分倒是没有任何难度,一般也没有什么坑) conda install jupyter notebook或者pi ...

  10. 记一次线上FGC问题排查

    引言 本文记录一次线上 GC 问题的排查过程与思路,希望对各位读者有所帮助.过程中也走了一些弯路,现在有时间沉淀下来思考并总结出来分享给大家,希望对大家今后排查线上 GC 问题有帮助. 背景 服务新功 ...