【Spring编程常见错误50例】03.依赖注入常见错误-上

1.多个实现类 如何匹配

在实际的开发中,我们会使用@Autowired 注解进行依赖注入对应的bean,但是如果我们依赖的是一个接口,有对应多个实现的话,就会出现异常。

@RestController
public class DbController {

    @Autowired
    private DbService dbService;

    @RequestMapping(path = "/hiDb",method = RequestMethod.GET)
    public String hiScope() {
        dbService.db();
        return "";
    }

}
@Service
public class MySQLDbService implements DbService{

    @Override
    public void db() {
        System.out.println("mysql init");
    }
}

@Service
public class HbaseDbService implements DbService{

    @Override
    public void db() {
        System.out.println("HbaseDB");
    }
}
Field dbService in com.qxlx.spingboot.controller.DbController required a single bean, but 2 were found:
	- hbaseDbService: defined in file [/Users/qxlx/work/qxlx/qxlx/spring/target/classes/com/qxlx/spingboot/service/HbaseDbService.class]
	- mySQLDbService: defined in file [/Users/qxlx/work/qxlx/qxlx/spring/target/classes/com/qxlx/spingboot/service/MySQLDbService.class]

原理分析

在这里插入图片描述

核心源码解析

AutowiredAnnotationBeanPostProcessor

	public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
	     // 找出依赖的字段和方法 构建元数据 通过递归的方式进行
		InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);
		// 完成对方法或者字段的注入 执行注入 将依赖注入到bean
		metadata.inject(bean, beanName, pvs);
		return pvs;
	}
	if (matchingBeans.size() > 1) {
		// 根据1.优先级@Primay来决策 2.@prority 3.bean名字
		autowiredBeanName = determineAutowireCandidate(matchingBeans, descriptor);
		if (autowiredBeanName == null) {
			// @Autowired是必须注入的, 注解的属性类型并不是可以接受的多个Bean类型
			if (isRequired(descriptor) || !indicatesMultipleBeans(type)) {
				return descriptor.resolveNotUnique(descriptor.getResolvableType(), matchingBeans);
			}
			else {
				return null;
			}
		}
	}

其实就是匹配多个条件,都不满足的时候,就抛出异常。因为没有办法决定使用那一个bean

解决方案

第一种 要么就是直接指定。

    @Autowired
    private DbService mySQLDbService;

第二种指定

	 @Autowired
	 @Qualifier("mySQLDbService")
	 private DbService dbService;

2.显示依赖bean首字母大小写 demo

但是如果我们故意写错了,回出现异常。

	 @Autowired
	 @Qualifier("MySQLDbService")
	 private DbService dbService;

异常信息

No qualifying bean of type 'com.qxlx.spingboot.service.DbService' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true), @org.springframework.beans.factory.annotation.Qualifier(value=MySQLDbService)}

具体原因

public String generateBeanName(BeanDefinition definition, BeanDefinitionRegistry registry) {
	// 如果是注解BD
	if (definition instanceof AnnotatedBeanDefinition) {
		// 查看bean是否有有name 有返回 
		String beanName = determineBeanNameFromAnnotation((AnnotatedBeanDefinition) definition);
		if (StringUtils.hasText(beanName)) {
			// Explicit bean name found.
			return beanName;
		}
	}
	// 设置一个默认的名称
	// Fallback: generate a unique default bean name.
	return buildDefaultBeanName(definition, registry);
}
protected String buildDefaultBeanName(BeanDefinition definition) {
	// 获取BeanClassName
	String beanClassName = definition.getBeanClassName();
	Assert.state(beanClassName != null, "No bean class name set");
	// 获取类名
	String shortClassName = ClassUtils.getShortName(beanClassName);
	// 生成类名
	return Introspector.decapitalize(shortClassName);
}
public static String decapitalize(String name) {
	// 基本验证
    if (name == null || name.length() == 0) {
        return name;
    }
    // 如果类名第一个和第二个都是大写 返回原来的类名
    // 比如 如果是MYSQLService 返回的就是MYSQLService
    if (name.length() > 1 && Character.isUpperCase(name.charAt(1)) &&
                    Character.isUpperCase(name.charAt(0))){
        return name;
    }
    char[] chars = name.toCharArray();
    //将第一个字母小写
    // 比如MySQLService 返回的就是mySQLService
    chars[0] = Character.toLowerCase(chars[0]);
    return new String(chars);
}

根据上述源码的分析,可以找到,在生成一个类名的时候,其实是有几个原则
1.如果类名提供了,那么按照对应的名称查找。
2.如果类名没有提供,并且前两个字母都是大写,那么默认就是原来的类名
3.类名是第一个字母小写。

掌握了上述原理,就可以轻松应对这些问题了。

3.引用内部类的bean类名

通过上面的案例,可以知道了beanName的规则,但是对于内部类来说。

@Service
public class MySQLDbService implements DbService{

    @Override
    public void db() {
        System.out.println("mysql init");
    }

    @Service
    public static class MySQLDbServiceImpl implements DbService{
        @Override
        public void db() {
            System.out.println("mysql init");
        }
    }
}
    @Autowired
    @Qualifier("MySQLDbService.MySQLDbServiceImpl")
    private DbService dbService;

发现出现错误。

No qualifying bean of type 'com.qxlx.spingboot.service.DbService' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true), @org.springframework.beans.factory.annotation.Qualifier(value=MySQLDbService.MySQLDbServiceImpl)}

原理分析

在生成类名的时候,有一个方法

String shortClassName = ClassUtils.getShortName(beanClassName);

public static String getShortName(String className) {
	Assert.hasLength(className, "Class name must not be empty");
	int lastDotIndex = className.lastIndexOf(PACKAGE_SEPARATOR);
	int nameEndIndex = className.indexOf(CGLIB_CLASS_SEPARATOR);
	if (nameEndIndex == -1) {
		nameEndIndex = className.length();
	}
	String shortName = className.substring(lastDotIndex + 1, nameEndIndex);
	shortName = shortName.replace(NESTED_CLASS_SEPARATOR, PACKAGE_SEPARATOR);
	return shortName;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/913655.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

智能母线插接箱监测装置的工作原理与实际应用分析

徐悦 安科瑞电气股份有限公司 随着电力系统的智能化发展,如何有效地监控电力系统的运行状态并保证系统安全性,成为电力运维中不可忽视的问题。AMB100智能母线直流监控装置应运而生。本文将详细介绍AMB100的工作原理及技术特点,结合实际应用…

USB包的结构

本文章主要来自《圈圈教你玩USB》的学习笔记 USB包的结构 USB是串行总线,所以数据是一位位的在数据总线上传输,采用LSB在前的方式。 USB数据需要经过位填充和NRZI编码。在这里讨论时,所用的数据都是原始数据,即没有经过位填充和…

让redis一直开启服务/自动启动

文章目录 你的redis是怎么打开的黑窗不能关?必须要自动启动吗?再说说mysql 本文的所有指令都建议在管理员权限下打开cmd控制台 推荐的以管理员身份打开控制台的方式 Win R 打开运行 输入cmdShift Ctrl Enter 你的redis是怎么打开的 安装过redis的朋友都知道, redis的安…

吴恩达深度学习笔记:卷积神经网络(Foundations of Convolutional Neural Networks)4.11

目录 第四门课 卷积神经网络(Convolutional Neural Networks)第四周 特殊应用:人脸识别和神经风格转换(Special applications: Face recognition &Neural style transfer)4.11 一维到三维推广(1D and 3…

基于图的去中心化社会推荐过滤器

🏡作者主页:点击! 🤖编程探索专栏:点击! ⏰️创作时间:2024年11月11日19点20分 点击开启你的论文编程之旅https://www.aspiringcode.com/content?id17176636216843&uideba758a1550b46bb…

云计算在教育领域的应用

💓 博客主页:瑕疵的CSDN主页 📝 Gitee主页:瑕疵的gitee主页 ⏩ 文章专栏:《热点资讯》 云计算在教育领域的应用 云计算在教育领域的应用 云计算在教育领域的应用 引言 云计算概述 定义与原理 发展历程 云计算的关键技…

开始使用 Elastic AI Assistant 进行可观察性和 Microsoft Azure OpenAI

作者:Jonathan Simon 按照此分步过程开始使用 Elastic AI Assistant for Observability 和 Microsoft Azure OpenAI。 最近,Elastic 宣布,AI Assistant for Observability 现已面向所有 Elastic 用户开放。AI Assistant 为 Elastic Observabi…

uniapp—android原生插件开发(1环境准备)

本篇文章从实战角度出发,将UniApp集成新大陆PDA设备RFID的全过程分为四部曲,涵盖环境搭建、插件开发、AAR打包、项目引入和功能调试。通过这份教程,轻松应对安卓原生插件开发与打包需求! 项目背景: UniApp集成新大陆P…

git新手使用教程

git新手使用教程 一、安装和初始化配置2、新建仓库3.工作区域和文件状态4.添加和提交文件5 git reset回退版本6 使用git diff查看差异7 使用git rm删除文件8 .gitignore忽略文件9 注册GitHub账号10 SSH配置和克隆仓库11 关联本地仓库和远程仓库12 Gitee的使用 由B站视频教程整理…

java程序优化二

接触渲染也有一段时间了,发现还有很多优化的空间,今天时间比较有限就提一点 一:从参数接口方面,例如提交渲染接口参数有大量的浮点数据,小数位过多,其实四舍五入保留4位也没什么影响,这样大小接…

分布式----Ceph部署(上)

目录 一、存储基础 1.1 单机存储设备 1.2 单机存储的问题 1.3 商业存储解决方案 1.4 分布式存储(软件定义的存储 SDS) 1.5 分布式存储的类型 二、Ceph 简介 三、Ceph 优势 四、Ceph 架构 五、Ceph 核心组件 #Pool中数据保存方式支持两种类型&…

在SpringBoot3中启用HTTP2

为什么要在SpringBoot中启用HTTP2 启用HTTP2可以带来更高效的数据传输、更优的性能表现以及更好的用户体验。 二进制格式传输数据:HTTP2采用二进制格式传输数据,而非HTTP1.x的文本格式,这使得协议解析更高效,且便于扩展。 头部压…

HCIP(核心技术篇)—RSTP实验配置

一、回顾STP和STP的缺点和不足 1.STP的概述: STP(生成树协议)是一种用于在网络中防止产生环路的链路管理协议。 2.STP的作用: 解决二层环路,防止广播报文产生。但是网络拓扑收敛较慢,影响通信质量。 3…

【数据库实验一】数据库及数据库中表的建立实验

目录 实验1 学习RDBMS的使用和创建数据库 一、 实验目的 二、实验内容 三、实验环境 四、实验前准备 五、实验步骤 六、实验结果 七、评价分析及心得体会 实验2 定义表和数据库完整性 一、 实验目的 二、实验内容 三、实验环境 四、实验前准备 五、实验步骤 六…

在线绘制cancer cell同款双向条形图展示富集结果

导读:将上调和下调pathway富集结果以双向条形图的形式在一张图中展示,不仅优化了绘图空间,还通过对称布局增强了图片的美观性。 《Cancer cell》文章“Cross-tissue human fibroblast atlas reveals myofibroblast subtypes with distinct ro…

Linux(文件特殊属性 + FACL 图片+大白话)

后面也会持续更新,学到新东西会在其中补充。 建议按顺序食用,欢迎批评或者交流! 缺什么东西欢迎评论!我都会及时修改的! 在这里真的很感谢这位老师的教学视频让迷茫的我找到了很好的学习视频 王晓春老师的个人空间…

json转excel,读取json文件写入到excel中【rust语言】

一、rust代码 将json文件写入到 excel中。(保持json :key原始顺序) use indexmap::IndexMap; use serde::Deserialize; use serde_json::{Value, from_str}; use std::error::Error; use std::io::{self, Write}; use std::path::{Path}; u…

理想火车站定位(字节青训)

题目 小F是A市的市长,正在计划在A市新建一个火车站以方便市民的日常出行。市区内的街道布局十分规整,形成网格状。从一个位置[x1, y1]到另一个位置[x2, y2]的距离计算方法为 |x1 - x2| |y1 - y2|,即曼哈顿距离。 在初步考察后,…

5位机械工程师如何共享一台工作站的算力?

在现代化的工程领域中,算力已成为推动创新与技术进步的关键因素之一。对于机械工程师而言,强大的计算资源意味着能够更快地进行复杂设计、模拟分析以及优化工作,从而明显提升工作效率与项目质量。然而,资源总是有限的,…

使用微信云开发,实现链接激活微信小程序(微信内部和外部H5访问)

首先小程序项目开发,需得支持云开发如何开通云开发?(网上教程很多,也很全面,这里仅带过) 配置云函数在项目根目录找到 project.config.json 文件,新增 cloudfunctionRoot 字段,指定本…