认识Spring(下)
作者:~小明学编程
文章专栏:Spring框架
格言:热爱编程的,终将被编程所厚爱。
目录
Spring更加高效的读取和存储对象
存储bean对象
五大注解
关于五大类注解
对象的注入
属性注入
构造方法注入
Setter注入
三种注入方式的区别
@Resource 和 @Autowired 的区别
Bean的作用域和生命周期
Spring的执行流程
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="com.beans"></content:component-scan>
</beans> 
首先是我们所依赖的资源,其中com.beans是我们所要扫描的类的包。
五大注解
- Controller 控制器
 - Service 服务
 - Repository 仓库
 - Configuration 配置
 - Component 组件
 
利用上面这五大注解都可以完成我们对象的注入。
@Service
public class UserService {public void sayHi() {System.out.println("hi Service");}
}
@Repository
public class UserRepository {public void sayHi() {System.out.println("Hi Res");}
}
@Controller
public class UserController {public void sayHi() {System.out.println("hello");}
}
@Configuration
public class UserConfig {public void sayHi() {System.out.println("Hi Con");}
}
@Component
public class UserComponent {public void sayHi() {System.out.println("Hi Com");}
} 
获取:
    public static void main1(String[] args) {//1.获取上下文ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");//2.得到beanUserController userController = context.getBean("userController",UserController.class);userController.sayHi();UserService userService = context.getBean("userService",UserService.class);userService.sayHi();UserRepository userRepository = context.getBean("userRepository",UserRepository.class);userRepository.sayHi();UserConfig userConfig = context.getBean("userConfig",UserConfig.class);userConfig.sayHi();UserComponent userComponent = context.getBean("userComponent",UserComponent.class);userComponent.sayHi();} 
获取的时候我们需要注意这个beanname,这个beanname是根据如下的逻辑。

关于五大类注解
既然我们五种注解的随便一种都能完成我们的对象的注入,那么我们为什么还是需要五种注解呢

因为我们一个软件是分为多个层面的,分为多层有助于我们的管理和控制。
Configuration 就是配置层:关于当前项目中的所有配置,都会写在这个文件夹里。
 Controller 就是控制层:就是前端参数校验,主要就是校验前端数据的合理性和正确性。
 Service 就是服务层,负责数据的组装和接口调用。更直白的说,服务器九四 “牵线搭桥” 让程序去调用对应的功能/接口/服务。
 Repository 叫做仓库,但其实是 数据持久层,也叫做 Dao 层,就是对数据进行持久化操作(对数据库进行增删改查操作)。
我们使用不同的注解便于我们了解不同的代码的功能同时也方便我们对代码进行一个管理。
当然这五大类注解之间是有一定的关系的:

可以看到我们的configuration注解是调用了我们的component注解的,其它几个注解的实现方法也是如此,可以说我们的component注解是我们其它四大注解的一个父类。
对象的注入
前面我们了解了怎么样将对象给存储起来,也就是使用五大注解可以高效方便的将我们的对象给放在spring中,但是当我们想要使用的时候有没有什么方式可以比较高效的来使用呢,下面就介绍三种方式来实现我们对象的一个注入。
属性注入
通过 @Autowired 注入:
@Controller
public class UserController {@Autowiredprivate UserService userService;public void sayHi() {userService.sayHi();}
} 
这里我们就通过关键字Autoeired的关键字来直接实现我们对象的一个注入,然在下面的方法之中我们就可以直接调用我们注入好的对象的方法了。
    public static void main(String[] args) {//1.获取上下文ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");UserController userController = context.getBean(UserController.class);userController.sayHi();//hi Service} 
构造方法注入
@Controller
public class UserController {
//    @Autowiredprivate UserService userService;public UserController(UserService userService) {this.userService = userService;}public void sayHi() {userService.sayHi();}
} 
这里我们可以直接通过构造方法的方式来进行对象的一个注入,但是值得我们注意的是,当我们的构造方法不止一个的时候就必须要使用Autowired关键字了,不然会报错。
@Controller
public class UserController {
//    @Autowiredprivate UserService userService;@Autowiredpublic UserController(UserService userService) {this.userService = userService;}public UserController(UserService userService,int num) {this.userService = userService;}public void sayHi() {userService.sayHi();}
} 
Setter注入
@Controller
public class UserController {private UserService userService;@Autowiredpublic void setUserService(UserService userService) {this.userService = userService;}public void sayHi() {userService.sayHi();}
} 
同样我们也可以使用Setter这样一个方法来进行一个注入。
三种注入方式的区别
- 属性注入特点是写法简单,但是通用性不好,只能运行在 IoC 容器下,如果是 非 IoC 容器的话,就会出现问题。
 - 构造方法注入,通用性更好。因为构造方法的优先级是最高的。确保使用注入对象之前,对象一定初始化过了。当构造方法注入参数太多时,就需要检查自己的代码是否符合单一设计原则的规范了。构造方法注入,也是 Spring 推荐的注入方法。
 - Setter 注入是早期 Spring 版本推荐的写法,但是通用性没有构造方法注入通用,因为只有一个参数。
 
@Resource 和 @Autowired 的区别
相同点:都可以完成对象的注入。
不同点:
- 出身不同,@Resource 来自于 JDK,@Autowired 是由 Spring 框架提供的。
 - @Autowired 支持属性注入,构造方法注入 和 Setter 注入,而 @Resource 不支持构造方法注入。
 - 支持的参数不同:@Resource 支持更多的参数设置,比如 name、type 设置。而 @Autowired 只支持 required 参数设置。
 
Bean的作用域和生命周期
在我们使用bean的时候其实默认是用的同一个bean也就是说如果我们对其中的bean进行一个更改的话,那么当我们再次去使用这个bean此时依然是更改之后的bean。
@Component
public class UserBean {@Bean(name = {"user","user1"})
//    @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)public User user2() {User user = new User(15,"lisi");return user;}@Bean(name = {"user2"})public User user1() {User user = new User(12,"zhangsan");return user;}
} 
@Component
public class BeanScope1 {@Autowiredprivate User user2;public User getUser() {user2.setStr("aaa");return user2;}
}
@Component
public class BeanScope2 {@Autowiredprivate User user2;//user2必须事被注入过的public User getUser() {return user2;}
} 
这个时候我们注入了两次bean对象,此时查看输入的结果:
    public static void main(String[] args) {ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");BeanScope1 beanScope1 = context.getBean(BeanScope1.class);System.out.println(beanScope1.getUser());BeanScope2 beanScope2 = context.getBean(BeanScope2.class);System.out.println(beanScope2.getUser());} 

可以看到我们在对其进行更改之后,再次注入仍然是更改之后的User。
产生这样的原因是因为 Bean 在 Spring 中,默认情况下是单例状态,也就是所有人的使用都是同一个对像。这样可以很好的节约资源,避免资源的浪费。
Bean 的六种作用域
singleton:单例作用域(默认)在这种模式下的 Bean 在 IoC 容器里面,只存在一个实例。
prototype:原型作用域(多例模式)每次对作用域下的 Bean 请求,都会创建新的实例,然后再去获取 Bean。
request:请求作用域(Spring MVC)每次 Http 请求会创建新的 Bean 实例,类似于 prototype。
session:会话作用域(Spring MVC)在一个 http session 中,定义一个 Bean 实例。记录用户的登录信息。
application:全局作用域(Spring MVC)更多人使用的时候,就用 application。也是单例模式,应用在 Web 应用的上下文信息。
websocket:Http WebSocket 作用域(Spring WebSocket)在 WebSocket 会话中使用。
当我们想要改变其作用域的时候可以通过@Scope 的注解来进行改变


可以看到此时我们 所注入的对象就都是新的对象了。
设置作用域的时候,只需要通过 @Scope 注解就可以了:
- 直接设置值:@Scope(“prototype”)
 - 使用枚举设置:@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
 
Spring的执行流程
1.我们首先是要启动我们的容器,去加载我们的配置文件。

也就是我们上面的这段代码。
2.接着就是根据我们的配置来完成我们的bean初始化。

通过扫描包中的spring注解。
3.注册 Bean 对象到容器中,只有在包扫描的路径上的类,且使用 Spring 的注解才可以被注册到容器当中。

4.装配 Bean 属性,也就是把 Bean 注册到其他类当中:

Bean的生命周期
Bean的生命周期就是Baen从诞生到销毁的一个过程 。
- 实例化 Bean(为 Bean 分配内存空间)
 - 设置属性(Bean 注入和装配)
 - Bean 初始化                                                                                                                         a)执行各种通知(各种Aware)如:BeanNameAware,BeanFactoryAware,ApplicationContextAware 的接口方法。
b)执行 BeanPostProcessor 初始化前置方法。
c)执行 @PostConstruct 初始化方法,依赖注入操作之后被执行。
d)执行自己指定的 init-method 方法(如果有指定的话
e)执行 BeanPostProcessor 初始化后置方法。 - 使用 Bean
 - 销毁 Bean,通过方法来销毁容器:如 @PreDestroy、DisposableBean、destroy-method
 

 其大概的流程图就是这样的。
<?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.beans"></content:component-scan><bean id="beanLife"class="com.beans.BeanLife" init-method="init"></bean>
</beans> 
package com.beans;import org.springframework.beans.factory.BeanNameAware;
import org.springframework.stereotype.Component;import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;/*** Created with IntelliJ IDEA.* Description:* User: 86184* Date: 2023-03-06* Time: 22:07*/
@Component
public class BeanLife implements BeanNameAware {@PostConstructpublic void Post() {System.out.println("PostConstruct");}@PreDestroypublic void Pre() {System.out.println("pre");}public void use() {System.out.println("use");}public void init() {System.out.println("init");}public void setBeanName(String s) {System.out.println("通知");}
}
 

执行流程如上。
相关文章:
认识Spring(下)
作者:~小明学编程 文章专栏:Spring框架 格言:热爱编程的,终将被编程所厚爱。 目录 Spring更加高效的读取和存储对象 存储bean对象 五大注解 关于五大类注解 对象的注入 属性注入 构造方法注入 Setter注入 三种注入方式的…...
Educational Codeforces Round 144 (Rated for Div. 2) C - Maximum Set
传送门 题意: 对于一个集合,如果它的任意两个元素都能 有 其中一个能整除另一个,那么它是好的。问在区间[L,R] 中由这个区间某些数内构成的好的集合的最长长度是多少,以及且满足这个长度的好集合有多少个。(懒得想就借…...
学python的第四天---基础(2)
一、三角形类型读入数组并排序的方法nlist(map(float,input().split())) c,b,asorted(n)list_1 list(map(float, input().split())) list_1.sort() list_1.reverse()lengthssorted(map(float,input().split(" ")),reverseTrue)二、动物写法一:d{" &…...
spring之refresh流程-Java八股面试(六)
系列文章目录 第一章 ArrayList-Java八股面试(一) 第二章 HashMap-Java八股面试(二) 第三章 单例模式-Java八股面试(三) 第四章 线程池和Volatile关键字-Java八股面试(四) 第五章ConcurrentHashMap-Java八股面试(五) 动态每日更新算法题,想要学习的可以关注一下…...
【C语言】刷题|链表|双指针|指针|多指针|数据结构
主页:114514的代码大冒 qq:2188956112(欢迎小伙伴呀hi✿(。◕ᴗ◕。)✿ ) Gitee:庄嘉豪 (zhuang-jiahaoxxx) - Gitee.com 文章目录 目录 文章目录 前言 一、移除链表元素 二、反转链表 三,链表的中间结点 四&…...
糖化学类854262-01-4,Propargyl α-D-Mannopyranoside,炔丙基 α-D-吡喃甘露糖苷
外观以及性质:Propargyl α-D-Mannopyranoside一般为白色粉末状,糖化学类产品比较多,一般包括:葡萄糖衍生物、葡萄糖醛酸衍生物,氨基甘露糖衍生物、半乳糖衍生物、氨基半乳糖衍生物、核糖衍生物、阿拉伯糖衍生物、唾液…...
项目管理工具DHTMLX 在 G2 排名中再创新高
DHTMLX Gantt是用于跨浏览器和跨平台应用程序的功能齐全的Gantt图表。可满足项目管理应用程序的大部分开发需求,具备完善的甘特图图表库,功能强大,价格便宜,提供丰富而灵活的JavaScript API接口,与各种服务器端技术&am…...
28 位委员出席,龙蜥社区第 15 次运营委员会会议顺利召开
2 月 24 日,龙蜥社区在海光召开了第 15 次运营委员会会议,本次会议由统信软件运营委员会委员崔开主持。来自 Arm、阿里云、飞腾、红旗软件、海光、Intel、龙芯、联通软研院、浪潮信息、普华基础软件、统信软件、万里红、移动、中科方德等理事单位的 28 位…...
自然语言处理-基于预训练模型的方法-chapter3基础工具集与常用数据集
文章目录3.1NLTK工具集3.1.1常用语料库和词典资源3.1.2常见自然语言处理工具集3.2LTP工具集3.3pytorch基础3.3.1张量基本概念3.3.2张量基本运算3.3.3自动微分3.3.4调整张量形状3.3.5广播机制3.3.6索引与切片3.3.7降维与升维3.4大规模预训练模型3.1NLTK工具集 3.1.1常用语料库和…...
【SpringMVC】@RequestMapping
RequestMapping注解 1、RequestMapping注解的功能 从注解名称上我们可以看到,RequestMapping注解的作用就是将请求和处理请求的控制器方法关联起来,建立映射关系。 SpringMVC 接收到指定的请求,就会来找到在映射关系中对应的控制器方法来处…...
【深度学习】BERT变体—SpanBERT
SpanBERT出自Facebook,就是在BERT的基础上,针对预测spans of text的任务,在预训练阶段做了特定的优化,它可以用于span-based pretraining。这里的Span翻译为“片段”,表示一片连续的单词。SpanBERT最常用于需要预测文本…...
根据身高体重计算某个人的BMI值--课后程序(Python程序开发案例教程-黑马程序员编著-第3章-课后作业)
实例3:根据身高体重计算某个人的BMI值 BMI又称为身体质量指数,它是国际上常用的衡量人体胖瘦程度以及是否健康的一个标准。我国制定的BMI的分类标准如表1所示。 表1 BMI的分类 BMI 分类 <18.5 过轻 18.5 < BMI < 23.9 正常 24 < BM…...
高并发编程JUC之进程与线程高并发编程JUC之进程与线程
1.准备 pom.xml 依赖如下: <properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><maven.compiler.source>1.8</maven.compiler.source><maven.compiler.target>1.8</maven.compiler.target&g…...
css基础
1-css引入方式内嵌式style(学习)<style>p {height: 200;}</style>外联式link(实际开发)<link rel"stylesheet" href"./2-my.css">2-选择器2.1标签选择器(标签名相同的都生效&am…...
Unity - 搬砖日志 - BRP 管线下的自定义阴影尺寸(脱离ProjectSettings/Quality/ShadowResolution设置)
文章目录环境原因解决CSharp 脚本效果预览 - Light.shadowCustomResolution效果预览 - Using Quality Settings应用ControlLightShadowResolution.cs ComponentTools Batching add the Component to all LightReferences环境 Unity : 2020.3.37f1 Pipeline : BRP 原因 (好久没…...
如何在SSMS中生成和保存估计或实际执行计划
在引擎数据库执行查询时执行的过程的步骤由称为查询计划的一组指令描述。查询计划在SQL Server中也称为SQL Server执行计划,我们可以通过以下步骤来生成和保存估计或实际执行计划。 估计执行计划和实际执行计划是两种执行计划: 实际执行计划:当执行查询时,实际执行计划出…...
mac 环境下安装MongoDB
目录 一、下载MongoDB数据库并进行安装 二. 解压放在/usr/local目录下 三. 配置环境变量 “无法验证开发者”的解决方法 mongodb可视化工具的安装与使用 一、下载MongoDB数据库并进行安装 下载地址:https://www.mongodb.com/try/download/community 二. 解压…...
RTOS中相对延时和绝对延时的区别
相信许多朋友都有过这么一个需求:固定一个时间(周期)去处理某一件事情。 比如:固定间隔10ms去采集传感器的数据,然后通过一种算法计算出一个结果,最后通过指令发送出去。 你会通过什么方式解决呢…...
Solon2 项目整合 Nacos 配置中心
网上关于 Nacos 的使用介绍已经很多了,尤其是与 SpringBoot 的整合使用。怎么安装也跳过了,主要就讲 Nacos 在 Solon 里的使用,这个网上几乎是没有的。 1、认识 Solon Solon 一个高效的应用开发框架:更快、更小、更简单…...
Linux 路由表说明
写在前面: 本文章旨在总结备份、方便以后查询,由于是个人总结,如有不对,欢迎指正;另外,内容大部分来自网络、书籍、和各类手册,如若侵权请告知,马上删帖致歉。 目录route 命令字段分…...
docker详细操作--未完待续
docker介绍 docker官网: Docker:加速容器应用程序开发 harbor官网:Harbor - Harbor 中文 使用docker加速器: Docker镜像极速下载服务 - 毫秒镜像 是什么 Docker 是一种开源的容器化平台,用于将应用程序及其依赖项(如库、运行时环…...
为什么需要建设工程项目管理?工程项目管理有哪些亮点功能?
在建筑行业,项目管理的重要性不言而喻。随着工程规模的扩大、技术复杂度的提升,传统的管理模式已经难以满足现代工程的需求。过去,许多企业依赖手工记录、口头沟通和分散的信息管理,导致效率低下、成本失控、风险频发。例如&#…...
Element Plus 表单(el-form)中关于正整数输入的校验规则
目录 1 单个正整数输入1.1 模板1.2 校验规则 2 两个正整数输入(联动)2.1 模板2.2 校验规则2.3 CSS 1 单个正整数输入 1.1 模板 <el-formref"formRef":model"formData":rules"formRules"label-width"150px"…...
如何在网页里填写 PDF 表格?
有时候,你可能希望用户能在你的网站上填写 PDF 表单。然而,这件事并不简单,因为 PDF 并不是一种原生的网页格式。虽然浏览器可以显示 PDF 文件,但原生并不支持编辑或填写它们。更糟的是,如果你想收集表单数据ÿ…...
算法笔记2
1.字符串拼接最好用StringBuilder,不用String 2.创建List<>类型的数组并创建内存 List arr[] new ArrayList[26]; Arrays.setAll(arr, i -> new ArrayList<>()); 3.去掉首尾空格...
【Nginx】使用 Nginx+Lua 实现基于 IP 的访问频率限制
使用 NginxLua 实现基于 IP 的访问频率限制 在高并发场景下,限制某个 IP 的访问频率是非常重要的,可以有效防止恶意攻击或错误配置导致的服务宕机。以下是一个详细的实现方案,使用 Nginx 和 Lua 脚本结合 Redis 来实现基于 IP 的访问频率限制…...
Python网页自动化Selenium中文文档
1. 安装 1.1. 安装 Selenium Python bindings 提供了一个简单的API,让你使用Selenium WebDriver来编写功能/校验测试。 通过Selenium Python的API,你可以非常直观的使用Selenium WebDriver的所有功能。 Selenium Python bindings 使用非常简洁方便的A…...
Python实现简单音频数据压缩与解压算法
Python实现简单音频数据压缩与解压算法 引言 在音频数据处理中,压缩算法是降低存储成本和传输效率的关键技术。Python作为一门灵活且功能强大的编程语言,提供了丰富的库和工具来实现音频数据的压缩与解压。本文将通过一个简单的音频数据压缩与解压算法…...
ZYNQ学习记录FPGA(一)ZYNQ简介
一、知识准备 1.一些术语,缩写和概念: 1)ZYNQ全称:ZYNQ7000 All Pgrammable SoC 2)SoC:system on chips(片上系统),对比集成电路的SoB(system on board) 3)ARM:处理器…...
Qt的学习(一)
1.什么是Qt Qt特指用来进行桌面应用开发(电脑上写的程序)涉及到的一套技术Qt无法开发网页前端,也不能开发移动应用。 客户端开发的重要任务:编写和用户交互的界面。一般来说和用户交互的界面,有两种典型风格&…...

