Spring更简单的存储和读取Bean

news2024/11/18 15:22:50

在这里插入图片描述

请添加图片描述

⭐️前言⭐️

在上一篇文章【Spring的创建与使用】中,我们已经了解了Spring中bean对象的基本的创建和使用方法,这篇文章通过注解的方法,使得存储和读取对象更加简单。

🍉博客主页: 🍁【如风暖阳】🍁
🍉精品Java专栏【JavaSE】、【备战蓝桥】、【JavaEE初阶】、【MySQL】、【数据结构】
🍉欢迎点赞 👍 收藏留言评论 📝私信必回哟😁

🍉本文由 【如风暖阳】 原创,首发于 CSDN🙉

🍉博主将持续更新学习记录收获,友友们有任何问题可以在评论区留言

🍉博客中涉及源码及博主日常练习代码均已上传码云(gitee)、GitHub


请添加图片描述

📍内容导读📍

  • 🍅1.存储Bean
    • 1.1 前置工作
    • 1.2 使用5大类注解实现存储
      • 1.2.1 @Controller(控制器存储)
      • 1.2.2 @Service(服务存储)
      • 1.2.3 @Repository(仓库存储)
      • 1.2.4 @Component(组件存储)
      • 1.2.5 @Configuration(配置存储)
    • 1.3 为什么需要这么多的注解?
    • 1.4 五大类注解之间的关系
    • 1.5 Spring使用五大类注解生成beanName
    • 1.6 通过@Bean方法注解实现存储
      • 1.6.1 方法注解要搭配类注解使用
      • 1.6.2 重命名Bean
  • 🍅2.获取Bean
    • 2.1 属性注入
    • 2.2 构造方法注入
    • 2.3 Setter注入
    • 2.4 三种注入方式的区别
    • 2.5 另一种注入注解`@Resourse`
    • 2.6 同一个类型多个@Bean报错
  • 🍅3.总结

请添加图片描述

🍅1.存储Bean

简单的将Bean存储到容器,有以下几种方法:

a)使用5大类注解实现
b)通过@Bean方法注解

下标我们一起来看具体的实现方式。

1.1 前置工作

在使用更简单的方法存储和读取bean对象之前,先完成前置工作——在Spring配置文件中设置bean的扫描根路径:

<?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=""></content:component-scan>
</beans>

在这里插入图片描述

1.2 使用5大类注解实现存储

1.2.1 @Controller(控制器存储)

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

@Controller
public class UserController {
    public void sayHi() {
        System.out.println("你好,Contorller");
    }
}

我们先使⽤之前读取对象的⽅式来读取上⾯的 UserController 对象,如下代码所示:

public class App {
    public static void main(String[] args) {
        //1.得到Spring上下文
        ApplicationContext context=
                new ClassPathXmlApplicationContext("spring-config.xml");
        //2.得到bean
        UserController userController=context.getBean("userController",UserController.class);
        //3.使用bean
        userController.sayHi();
    }
}

此处我们的beanName依旧是类名的小驼峰命名法,在后边我们会具体讲述Spring使用五大类注解生成beanName的问题。

1.2.2 @Service(服务存储)

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

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

读取bean的代码:

public class App {
    public static void main(String[] args) {
        //1.得到Spring上下文
        ApplicationContext context=
                new ClassPathXmlApplicationContext("spring-config.xml");
        //2.得到bean
        UserService userService=context.getBean("userService",UserService.class);
        //3.使用bean
        userService.sayHi();
    }
}

1.2.3 @Repository(仓库存储)

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

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

读取 bean 的代码:

public class App {
    public static void main(String[] args) {
        //1.得到Spring上下文
        ApplicationContext context=
                new ClassPathXmlApplicationContext("spring-config.xml");
        //2.得到bean
        UserRepository userRepository=context.getBean("userRepository",UserRepository.class);
        //3.使用bean
        userRepository.sayHi();
    }
}

1.2.4 @Component(组件存储)

使⽤ @Component 存储 bean 的代码如下所示:

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

读取 bean 的代码:

public class App {
    public static void main(String[] args) {
        //1.得到Spring上下文
        ApplicationContext context=
                new ClassPathXmlApplicationContext("spring-config.xml");
        //2.得到bean
        UserComponent userComponent=context.getBean("userComponent",UserComponent.class);
        //3.使用bean
        userComponent.sayHi();
    }
}

1.2.5 @Configuration(配置存储)

使⽤ @Configuration 存储 bean 的代码如下所示:

@Configuration
public class UserConfiguration {
    public void sayHi() {
        System.out.println("你好,Configuration");
    }
}

读取 bean 的代码:

public class App {
    public static void main(String[] args) {
        //1.得到Spring上下文
        ApplicationContext context=
                new ClassPathXmlApplicationContext("spring-config.xml");
        //2.得到bean
        UserConfiguration userConfiguration=context.getBean("userConfiguration",UserConfiguration.class);
        //3.使用bean
        userConfiguration.sayHi();
    }
}

1.3 为什么需要这么多的注解?

既然上述的五大类注解都能够完成将Bean对象存储到Spring中的功能,那为什么需要这么多的注解呢?

这是因为不同的注解有不同的用途,在程序猿看到类注解后,就能直接了解当前类的用途,增加了代码的可读性

程序的工程分层,调用流程如下:
在这里插入图片描述

1.4 五大类注解之间的关系

查看 @Controller / @Service / @Repository / @Configuration 等注解的源码发现:
在这里插入图片描述
这些注解里都有一个注解@Component,说明它们本身就是属于@Component的“子类”。

1.5 Spring使用五大类注解生成beanName

在1.2所有的获取bean对象的方法中,使用到的beanName都是小驼峰命名,但如果出现以下bean,还能通过小驼峰获取到吗?

@Controller
public class APIController {
    public void sayHi() {
        System.out.println("你好,APIController");
    }
}

在这里插入图片描述
在我们去还以小驼峰命名法去获取bean对象时,发现报错,说明并不是所有的beanName都是以小驼峰命名法来命名的。

我们来查看beanName的命名规则源码:
(关于注解beanName的生成器)
在这里插入图片描述
我们来看bean对象的命名规则的方法:
在这里插入图片描述
它使⽤的是 JDK Introspector 中的 decapitalize ⽅法,源码如下:

public static String decapitalize(String name) {
	 if (name == null || name.length() == 0) {
	 	return name;
	 }
	 // 如果第⼀个字⺟和第⼆个字⺟都为⼤写的情况,是把 bean 的⾸字⺟也⼤写存储了
	 if (name.length() > 1 && Character.isUpperCase(name.charAt(1)) &&
		 Character.isUpperCase(name.charAt(0))){
	 	return name;
	 }
	 // 否则就将⾸字⺟⼩写
	 char chars[] = name.toCharArray();
	 chars[0] = Character.toLowerCase(chars[0]);
	 return new String(chars);
}

如果第⼀个字母和第⼆个字母都为⼤写的情况,是把 bean 的⾸字母也⼤写存储了,否则就将⾸字母⼩写

所以对于上⾯报错的代码,我们只要改为以下代码就可以正常运⾏了:
在这里插入图片描述

1.6 通过@Bean方法注解实现存储

类注解是添加到某个类上的,而方法注解是放到某个方法上的,但仅依靠方法注解是仍然获取不到bean的,还需要搭配类注解:

1.6.1 方法注解要搭配类注解使用

先完成类代码:

public class User {
    private int id;
    private String name;

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", name='" + name + '\'' +
                '}';
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

@Component
public class UserBeans {
    @Bean
    public User getUser() {
        User user=new User();
        user.setId(1);
        user.setName("张三");
        return user;
    }
}

使用User类:
在这里插入图片描述
我们发现这样也可以获得User对象,但是beanName很别扭(也可以只通过bean type来获取该类,但如果出现多次存储的情况就会报错),因为是方法名,而不是类名的小驼峰,所以我们可以通过设置name属性给Bean对象,进行重命名操作,下边看具体演示:

1.6.2 重命名Bean

可以通过设置name属性给Bean对象进行重命名操作,如下代码所示:

@Component
public class UserBeans {
    @Bean(name="u1")
    public User getUser() {
        User user=new User();
        user.setId(1);
        user.setName("张三");
        return user;
    }
}

此时我们使用u1就可以获取到User对象了,如下代码所示:
在这里插入图片描述

🍅2.获取Bean

获取bean对象也叫做对象装配,是把对象取出来放到某个类中,有时候也叫对象注入

对象装配(对象注入)的实现方法有以下三种:

  • 属性注入
  • 构造方法注入
  • Setter注入

下边我们按照实际开发中的模式,将Service类注入到Controller类中。

2.1 属性注入

属性注入是使用@Autowired实现的,将Service类注入到Controller类中。

Service类的实现代码如下:

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

Controller类的实现代码如下:

@Controller
public class UserController2 {
    //属性注入
    @Autowired
    private UserService userService;

    public void sayHi() {
        userService.sayHi();
    }
}

获取 Controller 中的 sayHi⽅法:

在这里插入图片描述

2.2 构造方法注入

构造方法注入是在类的构造方法上,使用@Autowired实现注入,如下代码所示:

@Controller
public class UserController3 {
    private UserService userService;

    //构造方法注入
    @Autowired
    public UserController3(UserService userService) {
        this.userService = userService;
    }
    
    public void sayHi() {
        userService.sayHi();
    }
}

注意
如果只有一个构造方法,那么@Autowired注释可以省略,但如果类中有多个构造方法,就必须加上注解来明确指定到底使用哪个构造方法,否则会报错。

2.3 Setter注入

Setter注入和属性的Setter方法实现类似,只不过在设置set方法的时候需要加上@Autowired注解,如下代码所示:

@Controller
public class UserController4 {
    private UserService userService;
    
    //Setter注入
    @Autowired
    public void setUserService(UserService userService) {
        this.userService=userService;
    }
    
    public void sayHi() {
        userService.sayHi();
    }
}

2.4 三种注入方式的区别

  • 属性注入:写法简单,但是通用性不好,它只能运行在IoC容器下,如果是非IoC容器就会出现问题。
  • Setter注入:该注入方式是早期Spring版本推荐的方式,但Setter注入的通用性没有构造方法注入的通用性好。
  • 构造方法注入:通用性更好,它能确保在使用注入对象之前,此注入对象一定初始化过了。当构造方法参数较多时,开发者就要检查自己所写的代码是否符合单一设计原则的规范了,此注入方式也是Spring后期版本中推荐的注入方式

2.5 另一种注入注解@Resourse

该注入注解与@Autowired功能几乎相同,但也有差别,下边看两者的具体差别:

1、出身不同:@Resourse来自于JDK,而@Autowired是Spring框架提供的。
2、用法不同:@Autowired支持属性注入、构造方法注入和Setter注入,而@Resourse比前者少一个,它不支持构造方法注入。
3、支持的参数不同:@Resourse支持更多的参数设置,比如nametype设置,而@Autowired只支持required参数设置。

2.6 同一个类型多个@Bean报错

当出现以下多个Bean,返回同一对象类型时程序会报错,如下代码所示:

@Component
public class UserBeans {
    @Bean(name="u1")
    public User getUser1() {
        User user=new User();
        user.setId(1);
        user.setName("张三");
        return user;
    }
    @Bean(name="u2")
    public User getUser2() {
        User user=new User();
        user.setId(2);
        user.setName("李四");
        return user;
    }
}

在另一个类中获取User对象,如下代码所示:

@Controller
public class UserController {
    @Resource
    private User user;

    public void sayHi() {
        System.out.println("user->"+user);
    }
}

运行结果如下:
在这里插入图片描述
报错的原因是非唯一的Bean对象。

同一个类型多个Bean的报错处理有以下三种方式

1、精确地描述bean的名称(将注入的名称写对)
在这里插入图片描述
2、使用@Resourse设置name的方式来重命名注入对象
在这里插入图片描述
3、使用@Autowired+@Qualifier来筛选bean对象
在这里插入图片描述

🍅3.总结

1、将对象存储到Spring中:

  • 使用类注解:@Controller@Service@Repository@Configuration@Component【了解它们之间的关系与区别】
  • 使用方法注解:@Bean【注意搭配类注解一起使用】

2、Bean的命名规则:
首字母和第二个字母都是大写,那么直接使用原Bean名来获取Bean,否则就让首字母小写(小驼峰)来获取Bean。

3、从Spring中获取对象:

  • 属性注入
  • Setter注入
  • 构造函数注入(官方推荐)

4、注入的关键字:

  • @Autowired
  • @Resourse

5、 @Autowired@Resourse的区别:

  • 出身不同
  • @Resourse不支持构造方法注入
  • @Resourse支持更多的参数

6、解决同一类型多个Bean的报错:

  • 使用更精确的bean名称
  • 使用 @Resourse(name="")
  • 使用@Autowired @Qulifier("value =")

⭐️最后的话⭐️
总结不易,希望uu们不要吝啬你们的👍哟(^U^)ノ~YO!!如有问题,欢迎评论区批评指正😁

请添加图片描述

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

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

相关文章

[附源码]计算机毕业设计JAVA疫情背景下社区公共卫生服务系统

[附源码]计算机毕业设计JAVA疫情背景下社区公共卫生服务系统 项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a…

分布式事务最终一致性的方案

最终一致性的方案 知识储备 分布式系统中不可避免存在分布式事务带来的一致性问题。为了解决这个问题&#xff0c;需要熟悉业界相关的理论&#xff1a; ACID CAP BASE 2PC 3PC TCC 对于一致性的处理&#xff0c;分为强一致和最终一致性。强一致&#xff0c;对系统的吞吐…

cox回归RCS阈值效应函数cut.tab1.3发布

写在前面的话&#xff0c;本次只发布了cox回归RCS阈值函数&#xff0c;请看清楚再购买&#xff0c;觉得贵的可以等一等&#xff0c;这个函数最终会放在ggrcs包上面&#xff0c;免费供大家使用&#xff0c;急用的可以先看看。 接下来聊聊cox回归RCS阈值函数是干什么用的&#xf…

[附源码]Python计算机毕业设计SSM江西婺源旅游文化推广系统(程序+LW)

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

Python入门 函数 基础入门篇

一、什么是函数 函数是最基本的一种代码抽象的方式&#xff0c;是组织好的可重复使用的&#xff0c;用来实现单一或相关联功能的代码段。 函数是对做相似的事情或相似的动作进行封装&#xff0c;它能提高应用的模块性和代码的重复利用率。我们要封装好一个函数&#xff0c;首…

[附源码]计算机毕业设计设备运维平台出入库模块APPSpringboot程序

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

【STM32学习(3)】STM32——简述中断的基础知识

中断一、中断的定义二、中断的作用三、中断源&#xff08;中断触发的硬件&#xff09;四、中断类型五、中断优先级六、中断服务函数一、中断的定义 中断&#xff0c;即CPU在正常执行程序的过程中&#xff0c;遇到外部&#xff08;IO引脚中断&#xff09;/内部&#xff08;定时…

Maven技术

目录 传统项目管理分析&#xff08;导入jar包形式&#xff09; maven组成部分 maven项目构建命令 maven高级 项目的聚合与继承 maven子父工程 需求&#xff1a;使用maven子父工程完成登录并跳转到首页列表 创建父工程 在父工程中以module的形式创建子模块 在父工程中以…

RocketMQ 5.0 可观测能力升级:Metrics 指标分析

作者&#xff1a;玄珏 从消息的生命周期看可观测能力 在进入主题之前先来看一下 RocketMQ 生产者、消费者和服务端交互的流程&#xff1a; message produce and consume process RocketMQ 的消息是按照队列的方式分区有序储存的&#xff0c;这种队列模型使得生产者、消费者和…

Matlab论文插图绘制模板第67期—三角网格图(Trimesh)

在之前的文章中&#xff0c;分享了Matlab网格曲面图的绘制模板&#xff1a; 以及一些特殊形式的网格曲面图&#xff1a; 这一次&#xff0c;再来分享一种特殊的网格曲面图&#xff1a;三角网格图。 先来看一下成品效果&#xff1a; 特别提示&#xff1a;Matlab论文插图绘制模板…

为初学者介绍轻量级目录访问协议——LDAP

如果您是刚接触Active Directory (AD)的初学者&#xff0c;那么当您发现LDAP这个术语时可能会感到十分迷茫。今天就让我们来您熟悉 LDAP&#xff0c;让您更加坚定学习AD域管理的信心。 LDAP 首先&#xff0c;让我们直面主题&#xff01;什么是 LDAP&#xff1f; LDAP 是一种标…

[矩阵论] Unit 3. 矩阵的分解 - 知识点整理

注: 以下内容均由个人整理, 不保证完全准确, 如有纰漏, 欢迎交流讨论参考: 杨明, 刘先忠. 矩阵论(第二版)[M]. 武汉: 华中科技大学出版社, 2005 3 矩阵的分解 3.1 常见的矩阵标准形与分解 常见标准形 等价标准形: P,QP, QP,Q 可逆 AmnPmm[Ir000]QnnA_{m\times n}P_{m\times…

[附源码]Python计算机毕业设计SSM教师职称资料管理系统(程序+LW)

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

软件测试流程图!转行互联网职场必备!

今天给大家分享的是&#xff0c;在软件测试日常工作过程中&#xff0c;比较常见的几种测试流程图&#xff1a; 1.【测试立项】流程图 2.【测试计划】流程图 3.【单元测试】流程图 4.【整合测试】流程图 5.【系统测试】流程图 6.【性能测试】流程图 7.【验收测试】…

QTextStream(文本流)

QTextStream QTextStream 类为读取和写入文本提供了一个方便的接口可以在QIODevice、QBateArray、和QString中使用&#xff0c;QTextStream使用的是流运算符&#xff08;>> <<&#xff09;&#xff0c;可以更方便的读/写数据&#xff0c;QTextStream也支持对字段进…

使用 Echarts 插件完成中国地图

目录前言&#xff1a;什么是 Echarts 插件中国地图成品展示步骤&#xff1a;完成中国地图代码总结&#xff1a;前言&#xff1a; 大家都知道&#xff0c;一般情况下&#xff0c;想要使用前端设置一个 中国地图 需要使用 canvas 画布进行编写&#xff0c;不仅代码多&#xff0c…

【滤波器】基于Matlab设计巴斯 切比雪夫 椭圆 低通高通带通带阻数字滤波器附GUI界面

✅作者简介&#xff1a;热爱科研的Matlab仿真开发者&#xff0c;修心和技术同步精进&#xff0c;matlab项目合作可私信。 &#x1f34e;个人主页&#xff1a;Matlab科研工作室 &#x1f34a;个人信条&#xff1a;格物致知。 更多Matlab仿真内容点击&#x1f447; 智能优化算法 …

11月VR大数据:SteamVR新增PICO 4串流数据统计

Hello大家好&#xff0c;每月一期的VR内容/硬件大数据统计又和大家见面了。 想了解VR软硬件行情么&#xff1f;关注这里就对了。我们会统计Steam平台的用户及内容等数据&#xff0c;每月初准时为你推送&#xff0c;不要错过喔&#xff01; 本数据报告包含&#xff1a;Steam VR硬…

暖通锅炉远程监控解决方案

现状及需求分析 随着科学技术的发展&#xff0c;人们对生活品质的追求越来越高&#xff0c;空调行业也在快速发展&#xff0c;建筑空调已经成为现代城市不可或缺的重要组成部分。一般楼宇大厦都采用大型空调机组供暖制冷&#xff0c;那如何保证设备能恒温正常运行&#xff1f;…

[Python图像处理] 使用OpenCV检测对象颜色

使用OpenCV检测对象颜色前言使用 OpenCV 检测对象颜色相关链接前言 检测图像中对象颜色的一种简单方法是首先将图像从 RGB 转换为 HSV 颜色空间&#xff0c;然后使用一系列色调检测对象&#xff0c;这可以通过使用 OpenCV 库轻松完成。为了完成对象检测任务&#xff0c;我们需…