3. Spring 更简单的读取和存储对象(五大类注解 方法注解)

目录

1. 存储 Bean 对象

1.1 配置扫描路径

1.2 添加注解存储 Bean 对象

1.2.1 @Controller(控制器存储)

1.2.2 @Service(服务存储)

1.2.3 @Repository(仓库存储)

1.2.4 @Component(组件存储)

1.2.5 @Configuration(配置存储)

1.3 使用多个类注解的原因

1.3.1 五大注解之间的关系

1.3.1 Bean 的命名规则

1.4 方法注解 @Bean

1.4.1 方法注解要配合类注解使用

1.4.2 重命名 Bean

1.4.3 给有参数的方法添加 Bean 注解 

1.4.4 Spring xml 配置的方式进行传参

2. 根据日志定位问题

NoSuchBeanDefinitionException -- 没有找到 Bean


在 Spring 中想要更简单的存储和读取对象的核心是使用注解。

1. 存储 Bean 对象

之前我们存储 Bean 时,需要在 spring-config 中添加⼀行 bean 注册内容才行,如下图所示:

但是现在我们可以通过注解来代替上面的配置。

1.1 配置扫描路径

想要将对象成功的存储到 Spring 中,我们需要配置⼀下存储对象的扫描包路径,只有被配置的包下的所有类,添加了注解才能被正确的识别并保存到 Spring 中

在 spring-config.xml 添加如下配置:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:content="http://www.springframework.org/schema/context"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd"><content:component-scan base-package="com.bit.service"></content:component-scan>
</beans>

也就是说,即使添加了注解,如果不是在配置的扫描包下的类对象,也是不能被存储到 Spring 中的。

1.2 添加注解存储 Bean 对象

想要将对象存储在 Spring 中,有两种注解类型可以实现:

1. 类注解:@Controller、@Service、@Repository、@Component、@Configuration。

2. 方法注解:@Bean。

1.2.1 @Controller(控制器存储)

使用 @Controller 存储对象:

@Controller
public class UseController {public void sayHi(){System.out.println("hi,Controller...");}
}

接下来取对象:

public class App {public static void main(String[] args) {// 得到 Spring 上下文ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");// 获取 Bean 对象UserController user = (UserController) context.getBean("userController");// 使用 Beanuser.sayHi();}
}

可以发现在使用 getBean() 方法时,我们直接使用了注解下类名的小驼峰的形式,可以看到运行无误:

1.2.2 @Service(服务存储)

使用 @Service 存储对象:

@Service
public class UserService {public void sayHi(){System.out.println("Hi,Service...");}
}

 接下来取对象:

public class App {public static void main(String[] args) {// 得到 Spring 上下文ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");// 获取 Bean 对象UserService userService = (UserService)context.getBean("userService");// 使用 BeanuserService.sayHi();}
}
1.2.3 @Repository(仓库存储)

使用 @Repository 存储对象:

@Repository
public class UserRepository {public void sayHi(){System.out.println("Hi,Repository...");}
}

接下来取对象:

public class App {public static void main(String[] args) {// 得到 Spring 上下文ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");// 获取 Bean 对象UserRepository userRepository = (UserRepository)context.getBean("userRepository");// 使用 BeanuserRepository.sayHi();}
}
1.2.4 @Component(组件存储)

使用 @Component 存储对象:

@Component
public class UserComponent {public void sayHi(){System.out.println("Hi,Component...");}
}

 接下来取对象:

public class App {public static void main(String[] args) {// 得到 Spring 上下文ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");// 获取 Bean 对象UserComponent userComponent = (UserComponent)context.getBean("userComponent");// 使用 BeanuserComponent.sayHi();}
}
1.2.5 @Configuration(配置存储)

使用 @Configuration 存储对象: 

@Configuration
public class UserConfiguartion {public void sayHi(){System.out.println("Hi,Configuration...");}
}

 接下来取对象:

public class App {public static void main(String[] args) {// 得到 Spring 上下文ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");// 获取 Bean 对象UserConfiguartion userConfiguartion = (UserConfiguartion)context.getBean("userConfiguartion");// 使用 BeanuserConfiguartion.sayHi();}
}

1.3 使用多个类注解的原因

通过不同的类注解更加明确当前类的用途:

  • @Controller:表示的是业务逻辑层,控制器,通常是指程序的入口。比如参数校验、参数类型转换、前置处理工作等;
  • @Servie:服务层,一般写业务代码、服务编排、调用 DB、调用第三方接口等;
  • @Repository:持久层,仓库,通常是指 DB 操作相关的代码(Dao、mapper);
  • @Component:其他的对象;
  • @Configuration:配置层。
1.3.1 五大注解之间的关系

 查看 @Controller / @Service / @Repository / @Configuration 等注解的源码发现:

 这些注解里面都有⼀个注解 @Component,说明它们本身就是属于 @Component 的“子类”。

1.3.1 Bean 的命名规则

通过以上举例我们猜测:注解对应的 Bean 的名称是首字母小写。那么,真的如此吗?此时就需要我们去查看一下官方的文档。按住 CTRL + N 键进行搜索:

可以看到第四个是我们所需要的关于注解的,点进去后可以看到:

因此,我们得出结论:

当类名前两位均为大写时,需要返回自身类名;否则,返回首字母小写后的类名。

1.4 方法注解 @Bean

1.4.1 方法注解要配合类注解使用

类注解是添加到某个类上的,而方法注解是放到某个方法上的,如以下代码的实现:

public class Users {private String name;private Integer age;public String getName(){return name;}public void setName(String name){this.name = name;}public void setAge(Integer age){this.age = age;}
@Configuration
public class BeanConfig {@Beanpublic Users user(){Users user = new Users();user.setName("小明");user.setAge(18);return user;}public Users user2(){Users user = new Users();user.setName("小蓝");user.setAge(19);return user;}
}
public class App {public static void main(String[] args) {// 得到 Spring 上下文ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");// 获取 Bean 对象Users users = (Users) context.getBean("user");// 使用 BeanSystem.out.println(users.getName());}
}

@Bean 无法直接单独使用,必须搭配五大类注解使用。

Bean 对应生成的 Bean 名称是方法名。

1.4.2 重命名 Bean
@Configuration
public class BeanConfig {@Bean("aaa")public Users user(){Users user = new Users();user.setName("小明");user.setAge(18);return user;}public Users user2(){Users user = new Users();user.setName("小蓝");user.setAge(19);return user;}
}
@Configuration
public class BeanConfig {@Bean(name={"aaa","user"})public Users user(){Users user = new Users();user.setName("小明");user.setAge(18);return user;}public Users user2(){Users user = new Users();user.setName("小蓝");user.setAge(19);return user;}
}
@Configuration
public class BeanConfig {@Bean({"aaa","user"})public Users user(){Users user = new Users();user.setName("小明");user.setAge(18);return user;}public Users user2(){Users user = new Users();user.setName("小蓝");user.setAge(19);return user;}
}

以上三种方法均可实现 Bean 的重命名,重命名之后则无法使用原来的方法名来获取 Bean

 对五大类注解同样可以使用以上重命名的方法。

1.4.3 给有参数的方法添加 Bean 注解 
@Configuration
public class BeanConfig {@Bean({"aaa","user"})public Users user(Integer age){Users user = new Users();user.setName("小明");user.setAge(age);return user;}public Users user2(){Users user = new Users();user.setName("小蓝");user.setAge(19);return user;}
}

直接运行上述代码会报错,因为并没有找到 age 这个对象:

 此时修改代码如下:

@Configuration
public class BeanConfig {@Beanpublic Integer age(){return 15;}@Bean({"aaa","user"})public Users user(Integer age){Users user = new Users();user.setName("小明");user.setAge(age);return user;}public Users user2(){Users user = new Users();user.setName("小蓝");user.setAge(19);return user;}
}

 将对象交给 Spring 管理后,会自动匹配对应的类型,还可以通过其他方式去读取(比如配置文件中)。当只有一个 @Bean 注解时,根据类型进行匹配;当有多个 @Bean 时,根据名称进行匹配。

1.4.4 Spring xml 配置的方式进行传参
public class BeanConfig {public Users user(String name){Users user = new Users();user.setName(name);user.setAge(12);return user;}
}
<bean id="user" class="springcore"><constructor-arg name="name" value="小明"></constructor-arg>
</bean>

当需要注入的是对象时,要写引用:

public class UserController {private UserService userService;public UserController(UserService userService){this.userService = userService;}public void sayHi(){System.out.println("hi,Controller...");}
}
<bean id="user" class="springcore"><constructor-arg name="userService" ref="userService"></constructor-arg>
</bean>

2. 根据日志定位问题

NoSuchBeanDefinitionException -- 没有找到 Bean

Exception in thread "main" org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'userController' available

 没有名为“userController”的bean可用。

可以看到此时是因为注解被注释了,不再生效的原因。

出现以上日志时还有另一种可能原因,如下图所示:

也就是说当我们的扫描路径与实际不符时,同样会出现找不到 Bean 的情况。

除了以上两种情况当我们通过注解获取 Bean 时,类名不符合要求同样会生成以上的日志,具体如下图所示:

还有一种情况是因为将注解重命名了,但是使用的依然时未重命名之前的注解,同样会生成以上日志:

Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'java.lang.Integer' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {} 

没有可用的“java.lang.Integer”类型的限定bean。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

java项目之网络视频播放器(ssm+mysql+jsp)

风定落花生&#xff0c;歌声逐流水&#xff0c;大家好我是风歌&#xff0c;混迹在java圈的辛苦码农。今天要和大家聊的是一款基于ssm的网络视频播放器。技术交流和部署相关看文章末尾&#xff01; 开发环境&#xff1a; 后端&#xff1a; 开发语言&#xff1a;Java 框架&a…

ElementUI tabs标签页样式改造美化

今天针对ElementUI的Tabs标签页进行了样式修改&#xff0c;更改为如下图所属的样子。 在线运行地址&#xff1a;JSRUN项目-ElementUI tabs标签页样式改造 大家如果有需要可以拿来修改使用&#xff0c;下面我也简单的贴上代码&#xff0c;代码没有注释&#xff0c;很抱歉&#x…

【C++】开源:Muduo网络库配置与使用

&#x1f60f;★,:.☆(&#xffe3;▽&#xffe3;)/$:.★ &#x1f60f; 这篇文章主要介绍Muduo网络库配置与使用。 无专精则不能成&#xff0c;无涉猎则不能通。——梁启超 欢迎来到我的博客&#xff0c;一起学习&#xff0c;共同进步。 喜欢的朋友可以关注一下&#xff0c;下…

TSINGSEE青犀视频安防监控视频平台EasyCVR新增密码复杂度提示

智能视频监控平台TSINGSEE青犀视频EasyCVR可拓展性强、视频能力灵活、部署轻快&#xff0c;可支持的主流标准协议有国标GB28181、RTSP/Onvif、RTMP等&#xff0c;以及支持厂家私有协议与SDK接入&#xff0c;包括海康Ehome、海大宇等设备的SDK等&#xff0c;能对外分发RTSP、RTM…

pdf压缩到指定大小?纯压缩干货分享

在现代生活中&#xff0c;我们经常需要通过电子邮件或其他方式共享PDF文件&#xff0c;但是较大的PDF文件可能会遇到限制&#xff0c;这时候就需要将PDF文件压缩到指定大小。 很多朋友可能不知道怎么压缩PDF文件&#xff0c;我们可以首先了解下PDF文件压缩的原理&#xff0c;主…

opencv-17 脸部打码及解码

使用掩模和按位运算方式实现的对脸部打码、解码实例 代码如下&#xff1a; import cv2 import numpy as np #读取原始载体图像 lenacv2.imread("lena.png",0) #读取原始载体图像的 shape 值 r,clena.shape masknp.zeros((r,c),dtypenp.uint8) mask[220:400,250:350…

Java spring Aop实战

0目录 Spring AOP 1.实战 1.实战 创建工程和依赖 数据库建表 实体类 Mapper 接口 方法一 方法二 Service包 接口1&#xff1a; 实现接口 Mapper Mapper 1 Mapper 2 配置xml文件 Xml 1 Xml 2 Spring 配置文件 Mybatis配置文件 测试类 数据库结果 …

异地远程访问连接家里的群晖NAS【内网穿透】

文章目录 异地远程访问连接家里的群晖NAS【内网穿透】 异地远程访问连接家里的群晖NAS【内网穿透】 在现代企业中&#xff0c;协同办公和数据共享的作用已经受到广泛认可&#xff0c;而群晖作为小型数据处理中心&#xff0c;也已经进入很多公司&#xff0c;并成为局域网内的数…

Redis复制 (replica)

是什么 官网地址&#xff1a;Redis replication | Redis 其实就是主从复制&#xff0c;Master以写为主&#xff0c;Slave以读为主&#xff0c;当master数据变化的时候&#xff0c;自动将新的数据异步同步到其它slave数据库。 能干嘛 读写分离容灾恢复数据备份水平扩容支撑高并…

听GPT 讲K8s源代码--pkg(七)

k8s项目中 pkg/kubelet/config&#xff0c;pkg/kubelet/configmap&#xff0c;pkg/kubelet/container&#xff0c;pkg/kubelet/cri 这几个目录处理与 kubelet 配置、ConfigMap、容器管理和容器运行时交互相关的功能。它们共同构成了 kubelet 的核心功能&#xff0c;使其能够在 …

JAVA解析EXCEL(JExcelAPI,POI,EasyExcel)

前言 文章目录 前言JExcelAPIDemo POIHSSFWorkBookXSSFWorkBookDemo SXSSFWorkBookDemo XSSFReaderDemo EasyExcelDemo demo代码&#xff1a;https://github.com/RwTo/excel-demo JAVA解析Excel 一般有三种方式 JExcelAPI POI EasyExcel JExcelAPI 官网&#xff1a;https://je…

Vben Admin学习笔记

Modal 弹窗 modal弹窗一般作为单文件组件被引用&#xff0c;下面是两段示例代码&#xff1a; 弹窗文件 Modal.vue // Modal.vue <template><BasicModal v-bind"$attrs" title"Modal Title" :helpMessage"[提示1, 提示2]">Modal I…

【PostgreSQL内核学习(九)—— 查询执行(数据定义语句执行)】

数据定义语句执行 概述数据定义语句执行流程执行示例 声明&#xff1a;本文的部分内容参考了他人的文章。在编写过程中&#xff0c;我们尊重他人的知识产权和学术成果&#xff0c;力求遵循合理使用原则&#xff0c;并在适用的情况下注明引用来源。 本文主要参考了《PostgresSQL…

ES6 模块编程(新思路方便复习笔记)

文章目录 ES6 模块编程(新思路方便复习笔记)介绍需求说明思路分析/图解代码实现创建common.js创建use_common.js 其它导出形式--直接导出创建common2.js创建use_common2.js 其它导出形式--默认导出创建common3.js创建use_common3.js--导入默认导出模块/数据注意事项和使用细节导…

【应用】Asible自动化运维工具的应用与常用命令

ansible自动化运维工具 一、ansible 的概述1. ansible 的概念2. ansible 的特性 二、ansible 的部署与命令1. ansible 的部署1.1 服务器ip地址设置1.2 ansible 服务器部署 2. ansible 命令行模块2.1 command 模块2.2 shell 模块2.3 cron 模块2.4 user 模块2.5 group 模块2.6 co…

中国农业大学计算机考研分析

关注我们的微信公众号 姚哥计算机考研 更多详情欢迎咨询 中国农业大学&#xff08;B-&#xff09;考研难度&#xff08;☆☆☆&#xff09; 中国农业大学计算机考研招生学院是信息与电气工程学院。目前均已出拟录取名单。 中国农业大学信息与电气工程学院&#xff0c;起源于…

使用EasyPoi实现Excel的按模板样式导出

1&#xff0c;横向遍历 #fe 使用#fe命令可以实现集合数据的横向拓展&#xff0c;比如模板代码是 {{#fe:maths t.score}}导出的excel里面就会显示会自当前列&#xff0c;向右拓展&#xff0c;效果可参见下面的导出文件截图 2&#xff0c;横向遍历值 v_fe 使用v_fe命令可以实现…

ROS前驱前转小车仿真(2D)项目

文章目录 一.官方网址1.ROS官网2.urdf-模型3.rviz-数据可视化4.gazebo-仿真环境5.gmapping-建图6.navigation-导航 二.文件框架三.启动顺序0.依赖包的安装1.手动控制的启动顺序2.建图的启动顺序3.导航的启动顺序 四.urdf-模型文件1.ackermann.xacro-轮子传动的配置2.common_pro…

MAC 推送证书不受信任

配置推送证书的时候&#xff0c;一打开就变成不受信任&#xff0c;搜了很多解决版本。 由于苹果修改相关规定&#xff0c;推送证书 打开Apple PKI - Apple 下载AppleWWDRCA文件&#xff0c;选择G4,双击安装之后&#xff0c;证书已经变为受信任。 AppleWWDRCA(Apple Worldwid…

仿VScode MDK背景配色方案

效果如果所示 操作方法&#xff1a;备份后修改~/UV4文件夹下的global.prop&#xff0c;用以下的代码代替。 # properties for all file types indent.automatic1 virtual.space0 view.whitespace0 view.endofline0 code.page936 caretline.visible1 highlight.matchingbraces1…