【Spring】——Spring简单 读和取

news2024/11/29 9:49:00

前言 

❤️❤️❤️Spring专栏更新中,各位大佬觉得写得不错,支持一下,感谢了!❤️❤️❤️

Spring_冷兮雪的博客-CSDN博客

上期我们讲解了Spring的创建与使用,发现 将Bean 注册到容器 这一步中,如果Bean对象过多,在注册到容器时,我们有几个Bean对象就需要几行注册,在实际开发中这是非常麻烦的,我们需要有更简单的方法去实现这一过程,这便是本篇文章的主题——Spring简单 读和取。

 一、存储Bean对象[读]🍭

在Spring中我们可以使用注解存储和读取Bean对象,而其中我们有两种注解类型可以实现这个功能。

  1. 类注解:@Controller(控制器存储)、@Service(服务存储) 、@Repository(仓库存储)、@Component(组件存储)、@Configuration(配置存储)。
  2. 法注解:@Bean。

1、配置扫描路径🍉

但是在使用注解去进行存储和读取Bean对象之前,我们还需要进行配置扫描路径。在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.demo.component"></content:component-scan>
</beans>

 2、类注解🍉

Ⅰ、@Controller(控制器存储)🍓

 ArticleController类:

package com.demo.component;

import org.springframework.stereotype.Controller;

@Controller// 将对象存储到 Spring 中
public class ArticleController {
    public String sayHi(){
        return "Hello word";
    }
}

还是使用上篇讲的方法 去读取Bean对象:

import com.demo.component.ArticleController;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.core.io.ClassPathResource;

public class App {
    public static void main(String[] args) {
        //1、获取spring对象
        ApplicationContext context=new ClassPathXmlApplicationContext("spring-config.xml");
        //2、从Spring中取出Bean对象
        ArticleController articleController=(ArticleController) context.getBean("articleController");
        //3、使用Bean(可选)
        System.out.println(articleController.sayHi());//输出Hello word
    }
}

Ⅱ、@Service(服务存储)🍓

 ArticleController类:

package com.demo.component;

import org.springframework.stereotype.Service;

@Service// 将对象存储到 Spring 中
public class ArticleController {
    public String sayHi(){
        return "Hello word";
    }
}

还是使用上篇讲的方法 去读取Bean对象:

import com.demo.component.ArticleController;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.core.io.ClassPathResource;

public class App {
    public static void main(String[] args) {
        //1、获取spring对象
        ApplicationContext context=new ClassPathXmlApplicationContext("spring-config.xml");
        //2、从Spring中取出Bean对象
        ArticleController articleController=(ArticleController) context.getBean("articleController");
        //3、使用Bean(可选)
        System.out.println(articleController.sayHi());//输出Hello word
    }
}

Ⅲ、@Repository(仓库存储)🍓

 ArticleController类:

package com.demo.component;

import org.springframework.stereotype.Repository;


@Repository// 将对象存储到 Spring 中
public class ArticleController {
    public String sayHi(){
        return "Hello word";
    }
}

还是使用上篇讲的方法 去读取Bean对象:

import com.demo.component.ArticleController;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.core.io.ClassPathResource;

public class App {
    public static void main(String[] args) {
        //1、获取spring对象
        ApplicationContext context=new ClassPathXmlApplicationContext("spring-config.xml");
        //2、从Spring中取出Bean对象
        ArticleController articleController=(ArticleController) context.getBean("articleController");
        //3、使用Bean(可选)
        System.out.println(articleController.sayHi());//输出Hello word
    }
}

Ⅳ、@Component(组件存储)🍓

 ArticleController类:

package com.demo.component;

import org.springframework.stereotype.Component;

@Component// 将对象存储到 Spring 中
public class ArticleController {
    public String sayHi(){
        return "Hello word";
    }
}

还是使用上篇讲的方法 去读取Bean对象:

import com.demo.component.ArticleController;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.core.io.ClassPathResource;

public class App {
    public static void main(String[] args) {
        //1、获取spring对象
        ApplicationContext context=new ClassPathXmlApplicationContext("spring-config.xml");
        //2、从Spring中取出Bean对象
        ArticleController articleController=(ArticleController) context.getBean("articleController");
        //3、使用Bean(可选)
        System.out.println(articleController.sayHi());//输出Hello word
    }
}

Ⅴ、@Configuration(配置存储)🍓

package com.demo.component;

import org.springframework.context.annotation.Configuration;

@Configuration// 将对象存储到 Spring 中
public class ArticleController {
    public String sayHi(){
        return "Hello word";
    }
}

还是使用上篇讲的方法 去读取Bean对象:

import com.demo.component.ArticleController;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.core.io.ClassPathResource;

public class App {
    public static void main(String[] args) {
        //1、获取spring对象
        ApplicationContext context=new ClassPathXmlApplicationContext("spring-config.xml");
        //2、从Spring中取出Bean对象
        ArticleController articleController=(ArticleController) context.getBean("articleController");
        //3、使用Bean(可选)
        System.out.println(articleController.sayHi());//输出Hello word
    }
}

大家一路看下来,可能会吐槽一下:为什么全都是一样的代码啊?这有什么区别啊😂!

 为什么有这么多类注解?🍓

Spring框架有很多类注解是为了让开发者以更简洁、方便的方式来定义各种不同类型的Bean(如控制器、服务、存储库等),并且能够更容易地使用Spring的各种功能(如事务管理、缓存、安全性等)。虽然Spring框架中的注解很多,但 大多数都有特定的功能和用途,使得开发者可以根据需求选择合适的注解来使用,也可以让程序员看到类注解之后,就能直接了解当前类的用途,比如: 
  • @Controller(控制器):业务逻辑层,用来控制用户的行为,它用来检查用户参数的有效性。
  • @Servie(服务): 服务层,调用持久化类实现相应的功能。[不直接和数据库交互的,它类似于控制中心]
  • @Repository (仓库):持久层,是直接和数据库进行交互的。通常每一个表都会对应一个 @Repository。
  • @Configuration(配置):配置层,是用来配置当前项目的一些信息。
  • @Component (组件) : 公共工具类,提供某些公共方法。
程序的⼯程分层,调⽤流程如下:

五大类注解的联系🍓

直接看@Controller 、@Service 、@Repository 、@Configuration 等注解的源码:

@Service

@Repository

我们可以发现这些注解里面都有⼀个注解 @Component,说明它们是属于 @Component 的,是@Component的“子类”(其他源码也都类似,大家可以自行去查看查看他们的源码,理解更深刻哦!)。

3、Bean 的命名规则🍉

连续按两下 Shift 进行搜索或者通过下图方式去打开搜索框

 在 Classes中搜索 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时 ,Bean的命名只有两种:

  • 首字母和第⼆个字母都非大写,首字母小写来获取 Bean,
  • 首字母和第⼆个字母都是大写,那么直接使⽤原 Bean 名来获取

 类名为:ArticleController

正确命名方法:

错误命名方法:

 类名为:AController

 正确命名方法: 

错误命名方法:

4、方法注解Bean🍉

类注解是添加到某个类上的,而方法注解是放到某个方法上的。

Ⅰ、方法注解要配合类注解使用🍓

Bean注解需要配合五大类注解使用。
ArticleController
package com.demo.component;

import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;

@Component// 将对象存储到 Spring 中
public class ArticleController {
    private int id;
    private String 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;
    }

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

    @Bean//方法注解
    public ArticleController acSet(){
        ArticleController articleController=new ArticleController();
        articleController.setId(1);
        articleController.setName("java");
        return articleController;
    }
}

使用ArticleController中的acSet方法

import com.demo.component.ArticleController;
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、从Spring中取出Bean对象
        ArticleController articleController=(ArticleController) context.getBean("acSet");//命名规则和获取Bean一样
        //3、使用Bean(可选)
        System.out.println(articleController);
    }
}

当我们把acSet方法的@Component注解删除时,就会报错:

 因此,在使用Bean注解时需要配合使用五大类注解,才能将对象正常的存储到 Spring 容器中

Ⅱ、重命名 Bean🍓

可以通过设置 name 属性给 Bean 对象进行重命名操作。

 将acSet方法重命名为ac,并运行代码:

我们可以注意到重命名的name名是使用大括号进行存储,其实这就是⼀个数组,⼀个 bean 可以有多个名字。

aS:

import com.demo.component.ArticleController;
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、从Spring中取出Bean对象
        ArticleController articleController=(ArticleController) context.getBean("aS");
        //3、使用Bean(可选)
        System.out.println(articleController);//输出:ArticleController{id=1, name='java'}
    }
}

但是需要注意的是,如果进行了 重命名 原类名就无法再进行获取方法了!

二、获取 Bean 对象(对象装配)[取]🍭

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

1、依赖注入的常见方式 🍉

对象装配(对象注入)的实现方法以下 3 种:
  1. 属性注入
  2. 构造方法注入
  3. Setter 注入

 刚刚好这里有一篇有关Spring依赖注入的文章,写得很好,我就不重复造轮子了。

面试突击77:Spring 依赖注入有几种?各有什么优缺点? - 掘金 (juejin.cn)

Ⅰ、三种注入优缺点分析🍓

  1. 属性注⼊的优点是简洁,使同方便;缺点是只能用于 IoC 容器,如果是非 IoC 容器不可用,并且只有在使用的时候才会出现 NPE(空指针异常)。
  2. 构造⽅法注⼊是 Spring 推荐的注⼊方式,它的缺点是如果有多个注⼊会显得比较臃肿,但出现这种情况你应该考虑⼀下当前类是否符合程序的单⼀职责的设计模式了,它的优点是通用性,在使用之前⼀定能把保证注⼊的类不为空。
  3. Setter 方式是 Spring 前期版本推荐的注⼊方式,但通用性不如构造方法,所有 Spring 现版本已经推荐使⽤构造方法注⼊的方式来进行类注⼊了。

2、@Resource:另⼀种注入关键字🍉

在进⾏类注入时,除了可以使用 @Autowired 关键字之外,我们还可以使用 @Resource 进行注入

@Autowired 和 @Resource 的区别:

  • 出身不同:@Autowired 来⾃于 Spring,而@Resource 来自于 JDK 的注解;
  • 使用时设置的参数不同:相比于 @Autowired 来说,@Resource 支持更多的参数设置,例如 name 设置,根据名称获取 Bean。
  • @Autowired 可用于 Setter 注入、构造函数注⼊和属性注入,而@Resource 只能用于 Setter 注⼊和属性注⼊,不能用于构造函数注⼊。

 可以看到@Resource是JDK自带的方法:

构造函数注⼊时,@Resource 会报错:

 其实在官方文档中并没有明确指出为什么构造方法不可以使用@Resource 可能是官方类加载顺序的问题或者循环引用的问题。(可以评论区讨论,给出你的看法)

3、同⼀类型多个 @Bean 报错🍉

User

package com.demo.component;

public class User {
    private int id;
    private String 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;
    }

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

 Users

package com.demo.component;

import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;

@Component
public class Users {
    @Bean
    public User user1() {
        User user = new User();
        user.setId(1);
        user.setName("Java");
        return user;
    }
    @Bean
    public User user2() {
        User user = new User();
        user.setId(2);
        user.setName("MySQL");
        return user;
    }
}

UserController 

package com.demo.Controller;

import com.demo.component.User;
import org.springframework.stereotype.Controller;

import javax.annotation.Resource;

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

    public User getUser(){
        return user;
    }
}

运行APP 

 就可以看到 没有唯一Bean定义 异常

同⼀类型多个 Bean 报错处理 🍓

解决同⼀个类型,多个 bean 的解决方案有以下两个:
  • 使用@Resource(name="user1") 定义。
  • 使用@Qualifier 注解定义名称。

 使用@Resource(name="user1")

 使用@Qualifier 注解定义名称

 

 

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

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

相关文章

Matter协议高速崛起,你真的了解它吗?

今天我们要聊的话题&#xff0c;和智能家居有关。 说到智能家居&#xff0c;大家应该都不会陌生。早在本世纪初&#xff0c;物联网概念刚刚诞生的时候&#xff0c;最主要的应用领域&#xff0c;就是智能家居。 这些年来&#xff0c;随着数字技术的不断发展&#xff0c;越来越多…

MINIX 已死,Linux 又将如何呢?

导读MINIX 操作系统大约的确已经死了。Minix 原来是荷兰阿姆斯特丹的 Vrije 大学计算机科学系的 Andrew S. Tanenbaum 教授所开发的一个类 Unix 操作系统&#xff0c;全部代码共约 12,000 行&#xff0c;起初是为给学生讲解操作系统的运作细节而开发。 Linus Torvalds 也曾表示…

报表生成器FastReport .Net用户指南:“Rich Text“对象

FastReport .Net是一款全功能的Windows Forms、ASP.NET和MVC报表分析解决方案&#xff0c;使用FastReport .NET可以创建独立于应用程序的.NET报表&#xff0c;同时FastReport .Net支持中文、英语等14种语言&#xff0c;可以让你的产品保证真正的国际性。 FastReport.NET官方版…

1999-2020年31省省农村人口就业和文化程度相关数据

1999-2020年31省省农村人口就业和文化程度相关数据 1、时间&#xff1a; 2、范围&#xff1a;包括全国31省 3、来源&#xff1a;整理自各省NJ、统计NJ、农村NJ 4、指标包括&#xff1a; 乡村人口和乡村就业人员&#xff1a;乡村人口&#xff08;万人&#xff09;、乡村人口&…

opencv实践项目-停车位检测

目录 1. 步骤1.1 selector选择器1.2 detector探测器 2. 代码3. 效果图 1. 步骤 1.1 selector选择器 我们可以选择摄网络摄像头提供的第一帧&#xff0c;在该图像上选择停车位。为此&#xff0c;保存并使用该图像选择停车位。使用selectROIs函数标记停车位。ROI被定义为感兴趣…

分布式限流算法及实现介绍

分布式系统架构下面对突增的高并发访问请求&#xff0c;如何实现限流以保护系统的可用性是需要关注的一个问题。分布式限流实现机制上有很多中&#xff0c;包括基于网关实现、基于中间件如Redis实现等&#xff0c;本文简要介绍限流的常用算法以及实现方案。 1、分布式限流概述 …

Windows操作系统渗透测试

Windows操作系统渗透测试 任务环境说明&#xff1a;服务器场景名&#xff1a;Server02服务器场景操作系统&#xff1a;未知&#xff08;关闭链接&#xff09; 1.通过本地PC中渗透测试平台Kali对服务器场景进行系统服务及版本扫描渗透测试&#xff0c;并将该操作显示结果中808…

可视化报表系统推荐

在当今信息时代&#xff0c;数据的处理和分析已经成为了企业管理中不可或缺的一部分。而报表则是这个过程中最常见的工具之一。手工写报表虽然简单易懂&#xff0c;但是随着数据量的增加&#xff0c;这种方式逐渐暴露出许多痛点。比如说&#xff1a; 1.时间耗费长&#xff1a;…

Linux之进程间通信——管道

文章目录 前言一、进程间通信1.概念2.目的3.进程间通信分类 二、管道1.管道介绍2.管道分类1.匿名管道pipi创建管道文件&#xff0c;打开读写端fork子进程关闭父进程的读取端&#xff0c;关闭子进程的写入端读写特征管道特征 2.命名管道mkfifo创建管道文件删除管道文件通信 三、…

【openframework】实时路径规划(RTRRTstar算法)

程序框架 视频演示 实时RRT-star算法介绍 实时RRT-star算法是一种基于采样的运动规划算法&#xff0c;它可以在有限的时间内找到一条渐进最优的路径。实时RRT-star算法是在RRT-star算法的基础上进行了改进&#xff0c;主要有两个方面&#xff1a; - 实时更新起始点。实时RRT-st…

那些漏洞挖掘高手都是怎么挖漏洞的?

前言 说到安全就不能不说漏洞&#xff0c;而说到漏洞就不可避免地会说到三座大山&#xff1a; 漏洞分析 漏洞利用 漏洞挖掘 从个人的感觉上来看&#xff0c;这三者尽管通常水乳交融、相互依赖&#xff0c;但难度是不尽相同的。本文就这三者分别谈谈自己的经验和想法。 漏洞分析…

Mac图片批处理工具

PhotoMill X是一款强大的图像处理软件&#xff0c;它可以帮助用户快速地对照片进行编辑、调整和转换。它支持在单个或批量模式下处理大量的图像文件&#xff0c;并具有直观的用户界面和易于使用的工具。 PhotoMill X具有广泛的编辑功能&#xff0c;包括裁剪、缩放、旋转、调整明…

记录基于Vue.js的Tree组件_Liquor Tree

酒树 (Liquor Tree) A Vue tree component that allows you to present hierarchically organized data in a nice and logical manner. Vue 树组件&#xff0c;可让您以美观和逻辑的方式呈现层次结构的数据。 supports mobile, and has a variety of response events. Flex…

软考A计划-电子商务设计师-模拟试题卷三

点击跳转专栏>Unity3D特效百例点击跳转专栏>案例项目实战源码点击跳转专栏>游戏脚本-辅助自动化点击跳转专栏>Android控件全解手册点击跳转专栏>Scratch编程案例 &#x1f449;关于作者 专注于Android/Unity和各种游戏开发技巧&#xff0c;以及各种资源分享&am…

springboot+websocket客服聊天

续&#xff1a;spring boot 完整后端接口案例_cc&的博客-CSDN博客 后台代码 1.在pom.xml中添加spring-boot-starter-websocket <!--WebSocket--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter…

浅谈数明深力科隔离驱动器SLMi8235BD 车载充电器(OBC)方案

数明深力科SLMi823x系列SLMi8235BD隔离驱动技术优势&#xff1a;具有高性能、高性价比、高可靠性的产品特性&#xff0c;应用覆盖UPS、充电桩、服务器电源、通信电源、新能源汽车动力总成系统的车载 OBC 领域。通过CQC认证的。 车载充电器&#xff08;OBC&#xff09;是电动汽…

在线电子书创建:MkDocs + Github + ReadTheDocs

MkDocs是一个静态站点生成器&#xff0c;可用于构建项目文档。文档文件使用Markdown语法编写&#xff0c;本文记录如何使用MkDocs生成项目文档&#xff0c;并部署到Read the Docs上。 目录 安装mkdocs搭建文档项目创建项目启动项目编写文档Markdown语法站内链接图片 文档结构 配…

聚观早报 | 苹果收购AR头显初创公司Mira;抖音将尝试自营电商

今日要闻&#xff1a;苹果收购AR头显初创公司Mira&#xff1b;抖音将尝试自营电商&#xff1b;特斯拉股价实现九连涨&#xff1b;《黑镜》主创曾试用ChatGPT写剧本&#xff1b;携程集团发布2023Q1财报 苹果收购AR头显初创公司Mira 6 月 7 日消息&#xff0c;据 The Verge 报道…

2023免费电脑录视频软件Camtasia

Camtasia 2023是专业又好用的录屏软件&#xff0c;既可以用来录视频、ppt、直播课程等&#xff0c;也能够处理视频&#xff0c;添加各种效果&#xff0c;制作出更加满意的视频作品。Camtasia凭借愈发强大的功能收获了一大批忠实用户和如潮好评&#xff0c;已成为屏幕录制的必备…

6.16 @ 广州丨相约泛娱乐出海论坛,探寻市场突围的核心要义

1979 年&#xff0c;“出国办企业”第一次被有关部门提出&#xff0c;开启了中国企业对外投资的积极探索与尝试。经过 40 多年的耕耘&#xff0c;不少出海品牌已经站稳了脚跟&#xff0c;品牌影响力与日俱增&#xff0c;甚至在部分核心细分赛道上&#xff0c;中国企业凸显出了明…