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

news2025/1/9 2:02:16

目录

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");
        // 使用 Bean
        user.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");
        // 使用 Bean
        userService.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");
        // 使用 Bean
        userRepository.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");
        // 使用 Bean
        userComponent.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");
        // 使用 Bean
        userConfiguartion.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 {
    @Bean
    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;
    }
}
public class App {
    public static void main(String[] args) {
        // 得到 Spring 上下文
        ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
        // 获取 Bean 对象
        Users users = (Users) context.getBean("user");
        // 使用 Bean
        System.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 {
    @Bean
    public 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.coloradmin.cn/o/787577.html

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

相关文章

C语言学习笔记 Ubuntu系统下部署gcc编译工具-01

在22.04版本 ubuntu系统下&#xff1a; 1.进行apt工具包更新 sudo apt-get update 2.安装gcc工具 sudo apt-get install -y gcc 3.创建一下文件&#xff0c;并编译它输出相应的内容 touch hello.c 4.使用gcc编译c源程序并运行 格式&#xff1a;gcc 源文件名 -o 生成的执行文…

AcWing 1210. 连号区间数

输入样例1&#xff1a; 4 3 2 4 1输出样例1&#xff1a; 7输入样例2&#xff1a; 5 3 4 2 5 1输出样例2&#xff1a; 9样例解释 第一个用例中&#xff0c;有 77 个连号区间分别是&#xff1a;[1,1],[1,2],[1,3],[1,4],[2,2],[3,3],[4,4][1,1],[1,2],[1,3],[1,4],[2,2],[3,3…

记一次vscode配置CMake编译task的坑

事情经过是这样的&#xff0c;博主在一个项目中需要使用交叉编译链进行项目编译&#xff0c;但是在CMake中有一个自定义的编译选项&#xff0c;在vscode中配置task任务后&#xff0c;编译发现终端报静态库.a文件格式错误&#xff0c;如下图所示&#xff1a; 但是如果在CMakeLis…

python与深度学习(七):CNN和fashion_mnist

目录 1. 说明2. fashion_mnist实战2.1 导入相关库2.2 加载数据2.3 数据预处理2.4 数据处理2.5 构建网络模型2.6 模型编译2.7 模型训练2.8 模型保存2.9 模型评价2.10 模型测试2.11 模型训练结果的可视化 3. fashion_mnist的CNN模型可视化结果图4. 完整代码 1. 说明 本篇文章是C…

Install the Chinese input method on Linux

Open terminal and input: sudo -i apt install fcitx fcitx-googlepinyinWait for it to finish. Search fcitx: "设置"-->"输入法": Finally, we get the following result&#xff1a; Ctrl Space&#xff1a;Switch the input method. The test …

Redis追本溯源(三)内核:线程模型、网络IO模型、过期策略与淘汰机制、持久化

文章目录 一、Redis线程模型演化1.Redis4.0之前2.Redis4.0之后单线程、多线程对比3.redis 6.0之后 二、Redis的网络IO模型1.基于事件驱动的Reactor模型2.什么是事件驱动&#xff0c;事件驱动的Reactor模型和Java中的AIO有什么区别3.异步非阻塞底层实现原理 三、Redis过期策略1.…

印刷和数字设计的页面布局软件 QuarkXPress 2023 Crack

QuarkXPress 2023 用于印刷 和数字设计的页面布局软件&#xff0c;使用 QuarkXPress 释放您的创造力并最大限度地提高生产力 图形设计和桌面出版流程早就应该进行创新和颠覆&#xff0c;所以 QuarkXPress 就来了。自 1987 年首次亮相市场以来&#xff0c;成千上万的创意专业人士…

RocketMQ教程-(5)-功能特性-事务消息

事务消息为 Apache RocketMQ 中的高级特性消息&#xff0c;本文为您介绍事务消息的应用场景、功能原理、使用限制、使用方法和使用建议。 事务消息为 Apache RocketMQ 中的高级特性消息&#xff0c;本文为您介绍事务消息的应用场景、功能原理、使用限制、使用方法和使用建议。…

FFmpeg AVFilter的原理(三)- filter是如何被驱动的

1、下面是一个avfilter的graph 上图是ffmpeg中doc/examples中filtering_video.c案例的示意图。 本章节主要查看avfilter中的数据是怎么进入的&#xff0c;然后又是怎么出来的。 主要考察两个函数&#xff1a; av_buffersrc_add_frame_flags&#xff08;&#xff09;av_buffers…

gcc编译的时候出现错误,可以用core查看错误信息

比如说我们有文件main.c,threadpool.c,threadpool.h main.c和threadpool.c都用了threadpool.h,也就是#include "threadpool.h" &#xff08;1&#xff09;如果我们直接使用gcc main.c -o a.out -lpthread会报如下的错 我们需要进行动态库链接 gcc -c threadpool.c -…

驱动开发 day3 (模块化驱动启动led,蜂鸣器,风扇,震动马达)

模块化驱动启动led,蜂鸣器,风扇,震动马达并加上Makefile 封装模块化驱动&#xff0c;可自由安装卸载驱动&#xff0c;便于驱动更新(附图) 1.安装模块驱动同时初始化各个设备并使能 2.该驱动会自动创建驱动节点. 3.通过c函数程序输入控制各个设备 4.卸载模块驱动 //编译驱动…

裂缝二维检测:裂缝类型判断

裂缝类型选择 裂缝类型有很多种&#xff0c;这里我们判断类型的目的是要搞明白是否有必要检测裂缝的长度。在本文中&#xff0c;需要判断的裂缝类型共有四种&#xff1a;横向裂缝、纵向裂缝、斜裂缝、网状裂缝。 环境搭建 上一节骨架图提取部分&#xff0c;我们已经安装了sk…

Linux centos安装openoffice在线预览

前言&#xff1a;由于项目里需要用到word、excel等文件的在线预览&#xff0c;所有选择了openoffice 1、下载openoffice Apache OpenOffice - Official Download 大家自行选择需要安装的版本&#xff0c;楼主由于之前在其他服务器安装过&#xff0c;选择了之前用过的版本&am…

4.Docker数据管理和容器互联

文章目录 Docker数据管理数据卷&#xff08;容器与宿主机之间数据共享&#xff09;数据卷容器&#xff08;容器与容器之间数据共享&#xff09;容器互联 Docker数据管理 数据卷&#xff08;容器与宿主机之间数据共享&#xff09; 数据卷是一个供容器使用的特殊目录&#xff0…

【UE5 多人联机教程】03-创建游戏

效果 步骤 打开“UMG_MainMenu”&#xff0c;增加创建房间按钮的点击事件 添加如下节点 其中&#xff0c;“FUNL Fast Create Widget”是插件自带的函数节点&#xff0c;内容如下&#xff1a; “创建会话”节点指游戏成功创建一个会话后&#xff0c;游戏的其他实例即可发现&am…

mysql -速成

目录 1.概述 1.3SQL的优点 1.4 SQL 语言的分类 2. 软件的安装与启动 2.1 安装 2.2 MySQL服务的启动和停止 2.3 MySQL服务的登录和退出 ​编辑 2.4 mysql常用命令 2.5 图形化用户结构Sqlyong 3.DQL 语言 3.1 基础查询 3.1.1、语法 3.1.2 特点 3.2 条件查询 3.2.1 …

数据库的聚合函数和窗口函数

1. 聚合函数 数据库的聚合函数是用于对数据集执行聚合计算的函数。它们将一组值作为输入&#xff0c;并生成单个聚合值作为输出。聚合函数通常与GROUP BY子句结合使用&#xff0c;以便在数据分组的基础上执行聚合操作。 1.1. 常用的聚合函数 COUNT()&#xff1a;计算指定列或…

(五)springboot实战——springboot自定义事件的发布和订阅

前言 本节内容我们主要介绍一下springboot自定义事件的发布与订阅功能&#xff0c;一些特定应用场景下使用自定义事件发布功能&#xff0c;能大大降低我们代码的耦合性&#xff0c;使得我们应用程序的扩展更加方便。就本身而言&#xff0c;springboot的事件机制是通过观察者设…

Python(三十九)for-in循环

❤️ 专栏简介&#xff1a;本专栏记录了我个人从零开始学习Python编程的过程。在这个专栏中&#xff0c;我将分享我在学习Python的过程中的学习笔记、学习路线以及各个知识点。 ☀️ 专栏适用人群 &#xff1a;本专栏适用于希望学习Python编程的初学者和有一定编程基础的人。无…

JAVA设计模式——模板设计模式(heima)

JAVA设计模式——模板设计模式&#xff08;heima&#xff09; 文章目录 JAVA设计模式——模板设计模式&#xff08;heima&#xff09;一、模板类二、子类2.1 Tom类2.2 Tony类 三、测试类 一、模板类 package _01模板设计模式;public abstract class TextTemplate{public final…