Spring——利用五大类注解和Bean注解实现更简单的存储

news2025/1/11 12:48:41

目录

一、配置扫描路径

二、使用注解存储Bean对象

2.1 @Controller(控制器存储)

2.1.1 bean标签是否可以和component-san一起使用呢?

2.2 @Service(服务存储)

2.3 @Repository

2.4 @Component

2.5 @Configuration

2.6 五大类注解可以不在component-scan包下吗?

2.6.1 即使在component-scan 下,但是如果没有加五大类注解,一样是不能将当前对象存储到Spring:

2.6.2 在扫描路径(component -scan)下的所有子包下的类只要加了五大类注解,同样能存储到Spring中。

2.6.3 可能有的人会问,那出现在扫描路径下的不同包下存在相同的类名的情况,还能正常存储吗?

2.6 五大类注解之间的关系

2.6.1 为什么需要这么多注解

2.7 Bean的命名规则(源码)

2.8 使用方法注解(@Bean)存储Bean对象

2.8.1 方法注解得配合类注解使用

2.8.2 @Bean注解的重命名


前言:之前存储Bean时,我们是利用在Spring配置文件中添加一行 bean注册内容才行:

而现在我们只需要一个注解就可以替代之前要写整整一行配置的窘境了,在开始存储之前,我们需要做一些准备工作。

一、配置扫描路径

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

<?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">
<!--只有在com.java.demo包下的spring才去扫描有没有五大类的注解-->
    <content:component-scan base-package="com.java.demo"></content:component-scan>
</beans>

需要注意的是:

其中标红的一行为注册扫描的包:

二、使用注解存储Bean对象

想要将对象存储到Spring中,有两种注解类型可以使用:

  • 类注解:@Controller、@Service、@Repository、@Component、@Configuration。
  • 方法注解:@Bean。

2.1 @Controller(控制器存储)

使用@Controller 存储 bean 的代码如下所示:

package com.java.demo;

import org.springframework.stereotype.Controller;

@Controller //将当前类存储到spring当中
public class StudentController {
    public void sayHi() {
        System.out.println("do student controller sayHi()");
    }
}

这里我们先用ApplicationContext的方法来读取对象:

import com.java.demo.SController;
import com.java.demo.StudentController;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class App {
    public static void main(String[] args) {
        //1.得到Spring对象
        ApplicationContext context =
                new ClassPathXmlApplicationContext("spring-config.xml");
        //2.得到bean对象
        StudentController studentController =
                context.getBean("studentController",StudentController.class);
        //3.使用bean对象
        studentController.sayHi();

    }
}

可能有人会觉得奇怪,在getBean()方法中,传入的第一个参数之前是填写<Bean>标签中的id,但是现在不适用bean标签存储了,应该填什么呢?

先说结论:在使用类注解存Bean的时候,只存在两种情况:

  • 正常情况下,只需要将类名的首字母小写即可,也就是上述代码所展示的。
  • 特例:原类名如果首字母和第二个字母都是大写的情况下,那么bean的名称就是原类名。

以下为特例的展示:

代码运行结果:

2.1.1 bean标签是否可以和component-san一起使用呢?

经过验证:两者是可以一起存在的。

2.2 @Service(服务存储)

使用@Service存储bean的代码如下所示:

package com.java.demo;

import org.springframework.stereotype.Service;

@Service //将当前类存储到spring当中
public class StudentController2 {
    public void sayHi() {
        System.out.println("do student controller sayHi()");
    }
}

2.3 @Repository

使用@Repository存储bean的代码如下所示:

package com.java.demo;

import org.springframework.stereotype.Repository;

@Repository //将当前类存储到spring当中
public class StudentController3 {
    public void sayHi() {
        System.out.println("do student controller sayHi()");
    }
}

2.4 @Component

package com.java.demo;

import org.springframework.stereotype.Component;

@Component //将当前类存储到spring当中
public class StudentController4 {
    public void sayHi() {
        System.out.println("do student controller sayHi()");
    }
}

2.5 @Configuration

package com.java.demo;


import org.springframework.context.annotation.Configuration;

@Configuration //将当前类存储到spring当中
public class StudentController5 {
    public void sayHi() {
        System.out.println("do student controller sayHi()");
    }
}

这时候我们再使用ApplicationContext的方法来读取对象,会发现这五大类注解并没有什么区别。

2.6 五大类注解可以不在component-scan包下吗?

先说结论吧:不行的,Spring为了保持效率,只会扫描在component-scan包下的注解:

2.6.1 即使在component-scan 下,但是如果没有加五大类注解,一样是不能将当前对象存储到Spring:

2.6.2 在扫描路径(component -scan)下的所有子包下的类只要加了五大类注解,同样能存储到Spring中。

2.6.3 可能有的人会问,那出现在扫描路径下的不同包下存在相同的类名的情况,还能正常存储吗?

 一般情况下:是不行的,在加载Bean的时候就出现问题了:

如何修改呢?

  1. 直接将重名的类名修改掉
  2. 利用@Controller的方法,让该类名有一个别名。

我们来看看第二种方法的具体实现:

给在demo2下的包SController 添加别名:

运行结果: 

2.6 五大类注解之间的关系

观察@Controller、@Service、@Repository、@Configuration 源码发现,可以认为其都是@Component的 “子类”,都是针对@Component的一个扩展。

2.6.1 为什么需要这么多注解

前面我们给大家展示过了这些注解的使用,发现功能好像是没什么区别的,那为何设计了这么多的注解呢?

这和汽车的牌照是一样的,在当今交通网络发达的情况下,每个省的高速路口都可能出现来自不同省份的汽车,这可以帮助交警们迅速的识别这是来自哪个省份的汽车。

同样的注解也是相同,可以帮助程序员们快速的识别当前类的用途:

  • @Controller:控制层(业务逻辑层,主要用来验证前端,客户等发来的访问参数)
  • @Service:服务层(服务调度,相当于机场里的客服中心:用于导流等)
  • @Repository:数据持久层(直接操作数据库)
  • @Configuration:配置层

 程序的⼯程分层:

2.7 Bean的命名规则(源码)

通过在2.1 的示例,我们可以看出Bean的命名规则主要为两套:

  • 正常情况下,只需要将类名的首字母小写即可。
  • 特例:原类名如果首字母和第二个字母都是大写的情况下,那么bean的名称就是原类名

那我们来看看Spring关于Bean存储时生成的命名规则,

我们在idea中使用关键字搜索功能 “beanName”可以看到以下内容:

它使⽤的是 JDK Introspector 中的 decapitalize ⽅法,源码如下:

2.8 使用方法注解(@Bean)存储Bean对象

需要注意的是@Bean注解是将方法的返回值存到Spring中,所以返回值不能为空。

创建实体类User:

 运行结果:

2.8.1 方法注解得配合类注解使用

观察得出结论:@Bean注解得配合类注解使用才行——这是Spring为了提高性能而做出的规定。

试想,这种需要将方法返回值存到Spring中的事件是小众的,Spring是不可能为了这少部分的方法而去扫描在扫描路径下没有类注解的方法的。

再次执行以上代码:

2.8.2 @Bean注解的重命名

为什么需要对@Bean注解进行重命名呢?

这里我们在没有重命名的情况下是使用方法名来获取Bean,这未免有些不妥,不能够很好的表达Bean里面存储着什么,我们要做到望文生义。

观察@Bean的源码我们可以发现,可以利用name和value来进行对@Bean的重命名:

由于name和value具有相同的作用,因此这里我们使用name进行演示:

对@Bean注解起两个名字,这两个名字都是可以使用的,任意用哪个都行。

 再给其起了两个名字后,再次使用默认的方法名,发现程序报错。

如果在一个类中存在多个相同返回类型的方法,那么Spring可以正常读取吗?

 答案是:可以的。

以下为代码示例:

 如果在不同类中@Bean注解下有相同的返回值,会出现报错吗?

 答案是不会的,但是会出现新的值覆盖旧的值的情况:

这时候我们可以增加@Order注解来控制注入的顺序这一问题:

@Order里面的int值越小,权重值越高,就越先注入:


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

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

相关文章

27岁,测试在职近5年,月薪不到2W,担心被应届生取代

工作了近5年&#xff0c;一个月工资不到20K&#xff0c;担心被应届毕业生取代&#xff01;互联网的快速发展伴随着员工适者生存的加速&#xff0c;测试员的薪资也在不断增长&#xff0c;以3年、5年、8年为一条分水岭。如果人们的能力和体力不够&#xff0c;他们就会被淘汰。看起…

Android添加C++/CPP项目代码(2)

Android添加C/CPP项目代码&#xff08;2&#xff09; &#xff08;1&#xff09;选中某个module&#xff0c;右键&#xff0c;Add C to Module 在随后弹出的选项框中选第一个&#xff0c;OK。 &#xff08;2&#xff09;此时会在app下产生一个cpp目录和两个文件&#xff1a; x…

TiDB实战篇-BR进行数据备份与恢复

简介 使用BR进行数据备份与恢复。 原理 Backup备份的时候在PD上面找到表的元数据&#xff0c;然后找到对应的TiKV数据以后&#xff0c;直接备份到外部系统中&#xff08;注意如果没有像HDFS这样的分布式文件存储&#xff0c;那么它每个TiKV备份到本地的文件就只有一部分数据&…

nssctf web 入门(10)

[NISACTF 2022]midlevel [NISACTF 2022]midlevel 尝试使用x-forwarded-for 发现可行判断是不是ssti 确定是ssti模板注入 [NISACTF 2022]is secret [NISACTF 2022]is secret 根据这个我们去看看secret 这里看到这个猜测是通过get传入secret的值然后会机密我们的值 我们发现传…

优秀软件方法学“漫游记”

你好&#xff0c;我是东&#xff08;在极客时间的 ID 是 Fredo&#xff09;。大学的时候我读的是计算机专业&#xff0c;现在是一名工作了近3年的程序员&#xff0c;很高兴能和你分享我的学习体会。 我是怎样学习课程的&#xff1f; 首先聊聊我是怎么学习这门课的。 DDD 是一…

智网工程师培训一些心得

智网工程师培训一些心得 MYSQLApache Flask开发小程序 MYSQL MYSQL的日期如果定义为datetime类型&#xff0c;比较的时候可以使用 entry_form.exercise_date between 2022-1-1 and 2023-4-19 日期可以是非2位宽对齐方式 日期比较也可以使用大于或者小于号MYSQL支持定时备份数…

学习数据结构第6天(栈的基本概念)

栈的基本概念 栈的定义栈的基本操作栈的存储结构 栈的定义 栈(Stack)是一种基于先进后出(FILO)或者后进先出(LIFO)的数据结构&#xff0c;是一种只允许在一端进行插入和删除操作的特殊线性表。 栈按照先进后出的原则存储数据&#xff0c;先进入的数据被压入栈底&#xff0c;最…

数据结构初阶(链表)

文章目录 一、链表的基础概念1.1 什么是链表1.2 分类1.3 链表的底层代码1.4 例题1.5 LinkedList 的实现&#xff08;1&#xff09;什么是LInkedList&#xff08;2&#xff09;底层代码&#xff08;3&#xff09;LinkedLIst的使用 1.6 ArrayList和LinkedList的区别 一、链表的基…

Spring底层架构核心概念

文章目录 Spring底层架构核心概念BeanDefinitionBeanDefinitionReaderAnnotatedBeanDefinitionReaderXmlBeanDefinitionReaderClassPathBeanDefinitionScanner BeanFactoryApplicationContext国际化资源加载获取运行时环境事件发布 类型转换PropertyEditorConversionServiceTyp…

20行Python代码获取 心碎榜单文件保存本地,准备开始emo......

人生苦短 我用python&#xff08;emo版&#xff09; (语气充满悲伤…) 今天咱们试试只用20行代码来实现 批量获取 某某云 文件保存本地&#xff0c;炒鸡简单&#xff01; 悄悄的告诉你&#xff0c;其实不到20行代码~ 事前准备 软件环境 环境Python3.8编辑器是pycharm 模块…

轻松掌握k8s的kubectl使用命令行操作01知识点

程序员使用的kubectl&#xff0c;只能在主节点使用kubectl命令 1、查看集群所有节点 kubectl get nodes 2、根据配置文件&#xff0c;给集群创建资源 kubectl apply -f xxxx.yaml 3、查看集群部署了哪些应用 kubectl get pods -A 4、指定查看命名空间部署了哪些应用 不指…

[DSCoding2] 反转链表——迭代法

题目描述 核心思路 观察上图可以发现&#xff0c;将链表反转后&#xff0c;原有的结点间的引用关系发生了改变&#xff0c;比如反转前1指向2&#xff0c;反转后2指向1&#xff0c; 所以我们可以从修改节点间的引用关系下手。 在遍历链表时&#xff0c;将当前节点的next指针指向…

ReentrantLock原理

实现了Lock接口 内部也维护了一个同步器Sync继承自AQS&#xff0c;Sync是抽象的&#xff0c;两个实现NonFairSync和FairSync public ReentrantLock() {sync new NonfairSync(); } public ReentrantLock(boolean fair) {sync fair ? new FairSync() : new NonfairSync(); }非…

算法训练Day30:332.重新安排行程 51. N皇后 37. 解数独

文章目录 重新安排行程题解 [N 皇后](https://leetcode.cn/problems/n-queens/description/)题解 解数独题解 重新安排行程 CategoryDifficultyLikesDislikesContestSlugProblemIndexScorealgorithmsHard (47.57%)7650--0 Tags Companies 给你一份航线列表 tickets &#xf…

微服务学习——微服务

认识微服务 单体架构 将业务的所有功能集中在一个项目中开发&#xff0c;打成一个包部署。 优点: 架构简单部署成本低 缺点: 耦合度高 分布式架构 根据业务功能对系统进行拆分&#xff0c;每个业务模块作为独立项目开发&#xff0c;称为一个服务。 优点: 降低服务耦合有利…

【LeetCode】剑指 Offer 58. 反转字符串 p284 -- Java Version

1. 题目介绍&#xff08;58. 反转字符串&#xff09; 面试题58&#xff1a;翻转字符串&#xff0c; 一共分为两小题&#xff1a; 题目一&#xff1a;翻转单词顺序题目二&#xff1a;左旋转字符串 2. 题目1&#xff1a;翻转单词顺序 题目链接&#xff1a;https://leetcode.cn/p…

使用 ip2region 获取用户的 IP 归属地

目录 1. ip2region 简介2. 使用步骤2.1 下载资源2.2 引入依赖2.3 编写工具类2.3.1 获取 IP 地址2.3.2 根据 IP 地址获取 IP 归属地2.3.3 完整代码 2.4 结果测试 1. ip2region 简介 ip2region 是一个离线IP地址定位库和IP定位数据管理框架&#xff0c;10微秒级别的查询效率&…

部署zabbix代理服务器和snmp监控

目录 zabbix代理服务器 分布式监控的作用 部署zabbix代理服务器 在 Web 页面配置 agent 代理 snmp监控 SNMP简介 部署zabbix-snmp 服务端安装snmp监控程序 在 Web 页面配置 snmp 方式监控 zabbix代理服务器 分布式监控的作用 分担 server 的集中式压力 解决多机房之…

HTTP | 强缓存与协商缓存

缓存&#xff0c;开发绕不开的环节。 web缓存分为很多种&#xff0c;比如数据库缓存、代理服务器缓存、CDN缓存&#xff0c;以及浏览器缓存&#xff08;localStorage, sessionstorage, cookie&#xff09;。 一个web应用&#xff0c;需要各式各样的资源&#xff08;html/css/…

【C++】C++11 右值引用和移动语义

文章目录 一、左值与左值引用二、右值与右值引用三、左值引用和右值引用的比较四、右值引用的使用场景和意义1、左值引用的短板2、移动构造和移动赋值3、STL 容器的变化 五、万能引用与完美转发1、万能引用2、完美转发 六、新增默认成员函数七、成员变量的缺省值八、default 和…