Spring初识(三)

news2024/12/23 8:58:06

文章目录

  • 前言
  • 一.存储 Bean 对象
    • 1.1 类注解的用法
    • 1.2 为什么要使用这么多类注解
      • 1.2.1 为什么需要五大类注解
    • 1.3 各个类注解的关系
    • 1.4 Bean的命名规则
    • 1.5 方法注解的使用
  • 二.取出 Bean 对象
    • 2.1 属性注入
    • 2.2 Setter注入
    • 2.3 构造方法注入
  • 三.总结

前言

经过前面的学习,我们已经学会spring的存储对象和读取对象操作,我们简单的来回忆一下,上一篇文章的内容.存储操作如下:
操作容器之前,先要有容器,所以先要得到容器。

存对象
a.创建Bean(普通类)。
b.将 Bean注册(配置)到spring-confing.xml中。

取对象
a.得到Spring 上下文,并读取到Spring的配置文件。b.获取某一个 Bean对象。
c.使用Bean对象。
接下来我们会介绍比上面更加简单的方法,比如说注解的方法,大家耐心看我接下来的解释.

一.存储 Bean 对象

这里存储对象的方法大概有两种:
1.使用类注解:@Controller、@Service、@Repository、@Component、@Configuration
2.使用方法注解:@Bean
我们接下来会分别会对这些对象做出以下解释
1.各个注解的用法
2.为什么要使用这么多种类的注解
3.各个类注解之间的关系
4.存储Bean注解之间的命名关系
5.方法注解的用法.
我们在使用这些类注解之前,我们要配置扫描的路径.
在这里插入图片描述
在这里插入图片描述
配置扫描路径的意思是,我们想要将对象成功的存储到 Spring 中,我们需要配置⼀下存储对象的扫描包路径,只有被配置的包下的所有类,添加了注解才能被正确的识别并保存到 Spring 中.

1.1 类注解的用法

类注解的用法.
@Controller(控制器)注解的用法

@Controller
//将当前类存储到 spring当中
public class UserController {
    public void sayHi(String name) {

        System.out.println("Hi, UserController1");
    }
}

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

 //1.得到spring容器
        ApplicationContext context=new
                ClassPathXmlApplicationContext("spring-config.xml");
                //2.得到bean对象
 UserController userController=context.getBean("userController",UserController.class);
 //使用bean对象.
        userController.sayHi("张三");
        

@Service(服务存储)

@Service
//将当前类存储到 spring当中

public class UserController2 {
    public void sayHi() {

        System.out.println("Hi, UserController2");
    }

}

具体使用:

 //1.得到spring容器
        ApplicationContext context=new
                ClassPathXmlApplicationContext("spring-config.xml");
                //2.得到bean对象
 UserController userController=context.getBean("userController2",UserController2.class);
 //使用bean对象.
        userController.sayHi();
        

@ Resopsitory(仓库存储)

@Repository
//将当前类存储到 spring当中

public class UserController3 {
    public void sayHi() {

        System.out.println("Hi, UserController3");
    }
}

具体使用:

 //1.得到spring容器
        ApplicationContext context=new
                ClassPathXmlApplicationContext("spring-config.xml");
                //2.得到bean对象
 UserController userController=context.getBean("userController3",UserController3.class);
 //使用bean对象.
        userController.sayHi();

@Compentent(组件存储)使用方法

public class UserController4 {
    public void sayHi() {

        System.out.println("Hi, UserController4");
    }
}

具体使用:

 //1.得到spring容器
        ApplicationContext context=new
                ClassPathXmlApplicationContext("spring-config.xml");
                //2.得到bean对象
 UserController userController=context.getBean("userController4",UserController4.class);
 //使用bean对象.
        userController.sayHi();

@Configuration(配置存储)

@Configuration
//将当前类存储到 spring当中
public class UserController5 {
    public void sayHi() {

        System.out.println("Hi, UserController5");
    }
}

具体使用:

//1.得到spring容器
        ApplicationContext context=new
                ClassPathXmlApplicationContext("spring-config.xml");
                //2.得到bean对象
 UserController userController=context.getBean("userController5",UserController5.class);
 //使用bean对象.
        userController.sayHi();

1.2 为什么要使用这么多类注解

经过上面的介绍,我们注意到一个问题,既然每一个类注解都能加载到spring中,那我们为什么又要设计这么多注解类呢?这完全就是说不通的呀?

spring之所以要使用这么多注解,使用这些注解,开发人员可以在代码中直接表达配置和逻辑,而无需显式地编写XML配置文件。这大大简化了项目的配置和管理,提高了开发效率。同时,Spring框架支持自定义注解,开发人员也可以根据项目需求创建自己的注解,进一步提高代码的可读性和可维护性.
把这段话放在生活的例子中去说,就是我们每个省份的车牌号管理方式是一样的.
比如陕西的车牌号就是:陕X︰XXXXXX,北京的车牌号︰京X︰XXXXXX,一样。甚至一个省不同的县区也是不同的,比如西安就是,陕A︰XXXXX,咸阳:陕B︰XXXXXX,宝鸡,陕C: XXXXXX,一样。这样做的好处除了可以节约号码之外,更重要的作用是可以直观的标识一辆车的归属地。

这样一说明,就和我们上面的说法一一对上了.但是经过上述的解释之后,我们又要引出另外一个问题,为什么需要五大类注解?

1.2.1 为什么需要五大类注解

这个问题,我们换一个方向去思考,我们使用五大类的原因是什么?
很显然的话,我们是因为,如果我们是一个程序员的话,看到具体的注解,我们就知道这段代码是干什么,或者说,是让程序更清晰,更明了.
下面就是程序的分工和分层.
在这里插入图片描述
一般来说javaEE的基本分层就三层:
1.控制层
2.服务层
3.数据持久层

我们继续了解一下,阿里巴巴规定的规范结构.
在这里插入图片描述
经过两个对比之后,发现基本大相径庭.

1.3 各个类注解的关系

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

1.4 Bean的命名规则

这里为什么要单独提一嘴呢?我们拿取bean的操作的时候,是有语法规定的.
在这里插入图片描述

我这里直接说结论,后面带大家来解释一下:
我们读取的时候,情况如下:
1.是在bean对象正常使用大驼峰命名,使用小驼峰读取
2.假如不是大驼峰命名不是小驼峰,就直接返回当前类的类名即可.
具体例子如下:
在这里插入图片描述

为什么会发生这样的命名规则呢?具体的我们还是要看一下源码.
这就是我们对Bean的规则说明.
在这里插入图片描述

1.5 方法注解的使用

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

@Component
public class StudentBean {
    @Bean
    public Student student(){
        Student student=new Student();
        student.setAge(10);
        student.setUsername("zhangsan");
        return student;
    }

}

这里我们要取出来使用,代码如下:

public class App2 {
    public static void main(String[] args) {
        //1.得到spring容器
        ApplicationContext context=new ClassPathXmlApplicationContext("spring-config.xml");
        //2.获取到bean对象
      Student student=context.getBean("student", Student.class);
        //3使用
        System.out.println(student.toString());
    }
}

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

@Component
public class StudentBean2 {
    @Bean("stu1")
    public Student student(){
        Student student=new Student();
        student.setAge(10);
        student.setUsername("张飞");
        return student;
    }


}

接下来就可以通过stu1获取Student对象了.

public class App2 {
    public static void main(String[] args) {
        //1.得到spring容器
        ApplicationContext context=new ClassPathXmlApplicationContext("spring-config.xml");
        //2.获取到bean对象
      Student student=context.getBean("stu1", Student.class);
        //3使用
        System.out.println(student.toString());
    }
}

二.取出 Bean 对象

IoC 和 DI 是 Spring 中最重要的两个概念,其中 IoC(Inversion of Control)为控制反转的思想,而 DI(Dependency Injection)依赖注入为其(IoC)具体实现。那么 DI 实现依赖注入的方式有几种?这些注入方式又有什么不同?接下来,我们一起来看。

获取 bean对象也叫做对象装配,是把对象取出来放到某个类中,有时候也叫对象注入。
我们这里取出对象的方式也有以下几种方式:
1.属性注入
2.Setter注入
3.构造方法注入

接下来我们分别来看这几种注入的形式,这几种注入的形式,都是使用的一个注解

@Autowired
在这里插入图片描述

2.1 属性注入

属性注入是我们最熟悉,也是日常开发中使用最多的一种注入方式,它的实现代码如下:
先装配到spring中

@Service
//装入spring
public class StudentService {
    public void sayHi() {
        System.out.println("do studentService sayHi()");
    }
}

再通过属性注入,取出来

@Controller
public class StudentController {
    //1.属性注入
    @Autowired
    private StudentService studentService;
       public void sayHi(){
        System.out.println("com.java.demo -> do UserController sayHi()");
        studentService.sayHi();
    }


}

具体使用:

 StudentController studentController=context.getBean("studentController",StudentController.class);
        studentController.sayHi();

优缺点分析:
优点:属性注入最大的优点就是实现简单、使用简单
缺点:
1.无法注入一个不可变的对象(final 修饰的对象);
在这里插入图片描述

2.只能适应于 IoC 容器;
3.更容易违背单一设计原则。

2.2 Setter注入

@Controller
public class StudentController {
    private StudentService userService;
    @Autowired

    //2.setter注入
  public void setStudentService(StudentService studentService) {
        this.studentService = studentService;
    }


}

具体使用:

StudentController studentController=context.getBean("studentController",StudentController.class);
        studentController.sayHi();

优缺点分析:
优点: 要说 Setter 注入有什么优点的话,那么首当其冲的就是它完全符合单一职责的设计原则,因为每一个 Setter 只针对一个对象。
缺点:
1.不能注入不可变对象(final 修饰的对象);
在这里插入图片描述

2.注入的对象可被修改。

2.3 构造方法注入

@Controller
public class StudentController {
    private StudentService userService;
    // 3.构造方法注入

    @Autowired
    public StudentController( StudentService userService) {
        this.userService = userService;
    }
    public void sayHi(){
        System.out.println("com.java.demo -> do UserController sayHi()");
        userService.sayHi();
    }



}

具体使用:

StudentController studentController=context.getBean("studentController",StudentController.class);
        studentController.sayHi();
        

优缺点分析:
优点:

  1. 可注入不可变对象;
    原因:
    这是Java 的规定,在 Java 中,被final对象必须满足以下两个条件中的任意一个:
    a.final 修饰的对象,那么直接赋值;
    b.final修饰的对象,必须在构造方法中赋值。
  2. 注入对象不会被修改;
    因为构造方法只能只会执行一次
  3. 注入对象会被完全初始化;
  4. 通用性更好。

另外还要注意一点,这里除了使用@Autowired,还可以使用@Resource注解.但是Resource注解只能用在set方法和属性注入,构造方法是不能使用的.
代码案例如下:

public class StudentController {

@Resource
    private StudentService userService;
    
    }

具体使用:

 StudentService service=context.getBean("studentService",StudentService.class);
        service.sayHi();

下面继续介绍Resource的参数化设置的例子
代码如下:

现在存入两个相同的对象.

@Component
public class StudentBean {
    @Bean("student1")
    public Student student(){
        Student student=new Student();
        student.setAge(10);
        student.setUsername("zhangsan");
        return student;
    }
    @Bean
    public Student  getstudentbyname(){
        Student student=new Student();
        student.setAge(10);
        student.setUsername("lisi");
        return student;
    }

}

取出对象的参数

@Controller
public class StudentController3 {
    @Resource//更加简单的审批让容器中注入对象

    private Student student;
    public void sayHi(){
        System.out.println("com.java.demo -> do StudentController3 sayHi");
        System.out.println(student.getUsername());
    }

}

如果说直接这样取的话,会报一个错误.
大家请看:
在这里插入图片描述
大概就是没找到,但是我们Resource和Autowire已经有了方案,请看以下代码:
第一种:Resource 搭配name参数

@Controller
public class StudentController3 {
    @Resource(name = "student1")
  
    //更加简单的审批让容器中注入对象

    private Student student;
    public void sayHi(){
        System.out.println("com.java.demo -> do StudentController3 sayHi");
        System.out.println(student.getUsername());
    }

}

第二种: @Autowired搭配使用 @Qualifier 注解定义名称

@Controller
public class StudentController3 {
    @Autowired
    @Qualifier(value="student1")
    //更加简单的审批让容器中注入对象

    private Student student;
    public void sayHi(){
        System.out.println("com.java.demo -> do StudentController3 sayHi");
        System.out.println(student.getUsername());
    }

}

最后做个总结:
但是这两个注解之间是有区别的,具体的区别如下:
Autowired和@Resource 的区别

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

三.总结

  1. 将对象存储到Spring 中:
    a.使用类注解:@Controller、@Service、@Repository、@Configuration、@Component【它们之间的关系】
    b.使用方法注解:@Bean【注意事项:必须配合类注解一起使用】
  2. Bean 的命名规则:首字母和第二个字母都非大写,首字母小写来获取Bean,如果首字母和第二个字母都是大写,那么直接使用原Bean名来获取 Bean。
  3. 从 Spring中获取对象︰
    a.属性注入
    b.Setter注入
    c.构造函数注入(推荐)
  4. 注入的关键字有
    a.@Autowiredb.@Resource
  5. @Autowired和@Resource区别:出身不同;使用时设置参数不同@Resource支持更多的参数,比如name。
  6. 解决同一类型多个Bean的报错:
    a.使用@Resource(name=“”)b.使用@Qualifier(“”)

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

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

相关文章

【C++】STL使用仿函数控制优先级队列priority_queue

文章目录 前言一、priority_queue的底层实现二、使用仿函数控制priority_queue的底层总结 前言 本文章讲解CSTL的容器适配器:priority_queue的实现,并实现仿函数控制priority_queue底层。 一、priority_queue的底层实现 priority_queue叫做优先级队列&…

uview2.0使用u-calendar 的formatter属性,在formatter方法里无法访问this的bug,解决办法!!!!

uview 版本2.0.36 文档 使用该文档的案例,在 formatter打印this也会是undefined。 自己写了个demo 父给子传值v-bind传一个函数,然后在这个函数里面打印this,this是子组件的实例,但是不知道为什么formatter里会打印undefined。希…

pytorch工具——使用pytorch构建一个神经网络

目录 构建模型模型中的可训练参数假设输入尺寸为32*32损失函数反向传播更新网络参数 构建模型 import torch import torch.nn as nn import torch.nn.functional as Fclass Net(nn.Module):def __init__(self):super(Net,self).__init__()#定义第一层卷积层,输入维…

配置NFS服务

环境 环境 ubuntu 10.4 vm 7.1 终端 ifconfig 得到 ubuntu资料 INET ADDR 192.168.0.4 BCAST 192.168.0.255 MASK 255.255.255.0 操作前先关闭防火墙 关闭防火墙: 命令:sudo ufw disable 打开防火墙 命令:sudo ufw enable 配置过程 一 安…

G--爬山---2023河南萌新联赛第(二)场:河南工业大学

链接&#xff1a;登录—专业IT笔试面试备考平台_牛客网 来源&#xff1a;牛客网 示例1 输入 3 230 100 200 300 输出 192 示例2 输入 3 900 150 150 125 输出 -1 解析&#xff1a; 二分。 #include<bits/stdc.h> using namespace std; typedef long long ll…

单独在文件中打开allure生成的index.html报告时却显示为loading

【问题描述】&#xff1a;单独在文件中打开allure生成的index.html报告时显示为loading&#xff0c;如下图&#xff1a; 【问题定位】&#xff1a;其实在allure-report下index.html文件是不能直接打开的&#xff0c;出现页面都是loading的情况&#xff0c;这是因为直接allure报…

回归预测 | MATLAB实现TCN-BiGRU时间卷积双向门控循环单元多输入单输出回归预测

回归预测 | MATLAB实现TCN-BiGRU时间卷积双向门控循环单元多输入单输出回归预测 目录 回归预测 | MATLAB实现TCN-BiGRU时间卷积双向门控循环单元多输入单输出回归预测预测效果基本介绍模型描述程序设计参考资料 预测效果 ![6 基本介绍 1.MATLAB实现TCN-BiGRU时间卷积双向门控循…

RT-Thread qemu mps2-an385 bsp 移植制作 :系统启动篇

前言 前面准备了 RT-Thread qemu mps2-an385 bsp 制作相关的环境与相关文件&#xff0c;本篇开始讲解 bsp 如何适配到 RT-Thread CPU 部分已经适配好了&#xff0c;也就是通过 使能 ARCH_ARM_CORTEX_M3 &#xff0c;来使能 rt-thread/libcpu/arm/cortex-m3&#xff0c;这部分不…

使用docker进行MYSQL主从复制(一主两从)

目录 概述主从介绍 主从作用 主从作用有&#xff1a; 主从形式有&#xff1a; 配置步骤 主要配置 1>创建三个进程 2>修改配置文件 3>主机配置 4>从机配置 5>将文件修改后&#xff0c;复制到容器里面 6>进入主机进行配置 6.1>创建用户 6.2>…

从0到1完成UI自动化测试框架搭建之Pytest

上篇文章中&#xff0c;我们学会了如何使用UI Automator2atx编写简单的Android自动化脚本。 但是有个问题&#xff0c;大家可以思考下&#xff0c;光用自动化脚本让它自己动起来&#xff0c;是不是缺了点什么&#xff1f; 我们写测试用例的时候&#xff0c;是不是经常写&…

【C++】string的深入学习与模拟实现

&#x1f680;write in front&#x1f680; &#x1f4dc;所属专栏&#xff1a;初阶数据结构 &#x1f6f0;️博客主页&#xff1a;睿睿的博客主页 &#x1f6f0;️代码仓库&#xff1a;&#x1f389;VS2022_C语言仓库 &#x1f3a1;您的点赞、关注、收藏、评论&#xff0c;是对…

Python 模块 ddt 数据驱动测试

简介 ddt 提供了一种方便的方法来实现数据驱动测试&#xff08;Data-Driven Testing&#xff09;。数据驱动测试是一种测试方法&#xff0c;通过将测试数据与测试逻辑分开&#xff0c;可以使用不同的数据集来运行相同的测试用例。这样可以提高测试的灵活性和可维护性&#xff0…

SQL SERVER ANALYSIS SERVICES决策树、聚类、关联规则挖掘分析电商购物网站的用户行为数据...

全文链接&#xff1a;http://tecdat.cn/?p32118 假如你有一个购物类的网站&#xff0c;那么你如何给你的客户来推荐产品呢&#xff1f;&#xff08;点击文末“阅读原文”获取完整文档、数据&#xff09; 相关视频 这个功能在很多电商类网站都有&#xff0c;那么&#xff0c;通…

Flink CEP (一)原理及概念

目录 1.Flink CEP 原理 2.Flink API开发 2.1 模式 pattern 2.2 模式 pattern属性 2.3 模式间的关系 1.Flink CEP 原理 Flink CEP内部是用NFA&#xff08;非确定有限自动机&#xff09;来实现的&#xff0c;由点和边组成的一个状态图&#xff0c;以一个初始状态作为起点&am…

Unity进阶-消息框架的理论知识与实际操作学习笔记

文章目录 Unity进阶-消息框架的理论知识与实际操作学习笔记 Unity进阶-消息框架的理论知识与实际操作学习笔记 笔记来源课程&#xff1a;https://study.163.com/course/courseMain.htm?courseId1212756805&_trace_c_p_k2_8c8d7393c43b400d89ae94ab037586fc 这种框架其实…

实现锂电池形状的数据可视化css+js

1.效果图 2.需求根据后端返回数据改变里面的高度 HTML&#xff1a; <div class"dianchichi"><div class"limian" id"divElementId"></div></div> css: .dianchichi {width: 84px;height: 146px;display: flex;justify-…

Two Days wpf 分享 分页组件

迟来的wpf分享。 目录 一、序言 二、前期准备 三、前端界面 四、后台代码部分 1、先定义些变量后面使用 2、先是按钮事件代码。 首页按钮 上一页按钮 下一页按钮 末尾按钮 画每页显示等数据 每页显示多少条 判断是否为数字的事件 分页数字的点击触发事件 跳转到…

Docker安装Nexus并配置Maven私服

1 准备工作 1 服务器已安装docker, docker各命令无报错 2 通过dockerhub查看nexus的版本信息&#xff0c;此次使用的镜像为&#xff1a;sonatype/nexus3&#xff0c;可以看到latest版本更前的的是3.58.0&#xff0c;我们这次就使用这个版本的nexus3. 2 开始安装 # 下载镜像 do…

springcloudAlibaba之springboot如何加载nacos配置文件

配置文件想必大家都很熟悉&#xff0c;无论什么架构 都离不开配置&#xff0c;虽然spring boot已经大大简化了配置&#xff0c;但如果服务很多 环境也好几个&#xff0c;管理配置起来还是很麻烦&#xff0c;并且每次改完配置都需要重启服务&#xff0c;nacos config出现就解决了…

【JavaEE】Servlet常用的API

目录 前言 一、HttpServlet类 1、Servlet的生命周期 ✨tomcat的两个端口 ✨设置告诉浏览器使用那种字符集解析响应 ✨Java中Unicode和utf8字符集的使用 二、HttpServletRequest类 1、获取请求的信息 2、 前端给后端传递数据的三种方式 2.1、通过query string传递 2.2…