Spring - 5 ( 8000 字 Spring 入门级教程 )

一:Spring IoC&DI

1.1 方法注解 @Bean

类注解是添加到某个类上的, 但是存在两个问题:

  1. 使用外部包里的类, 没办法添加类注解
  2. ⼀个类, 需要多个对象, ⽐如多个数据源

这种场景, 我们就需要使用方法注解 @Bean

我们先来看方法注解如何使用:

public class BeanConfig {@Beanpublic User user(){User user = new User();user.setName("zhangsan");user.setAge(18);return user;}
}

然而,当我们写完以上代码,尝试获取 bean 对象中的 user 时却发现,根本获取不到:

@SpringBootApplication
public class SpringIocDemoApplication {public static void main(String[] args) {//获取Spring上下⽂对象ApplicationContext context = SpringApplication.run(SpringIocDemoApplication.class, args);//从Spring上下⽂中获取对象User user = context.getBean(User.class);//使⽤对象System.out.println(user);}
}

以上程序的执行结果如下:

在这里插入图片描述

这是为什么呢?

1.1.1 方法注解要配合类注解使用

在 Spring 框架的设计中,方法注解 @Bean 要配合类注解才能将对象正常的存储到 Spring 容器中,如下代码所示:

@Component
public class BeanConfig {@Beanpublic User user(){User user = new User();user.setName("zhangsan");user.setAge(18);return user;}
}

再次执行以上代码,运行结果如下:

在这里插入图片描述

1.1.2 定义多个对象

对于同⼀个类, 如何定义多个对象呢,比如多数据源的场景, 类是同⼀个, 但是配置不同, 指向不同的数据源.

我们看下 @Bean 的使用

@Component
public class BeanConfig {@Beanpublic User user1(){User user = new User();user.setName("zhangsan");user.setAge(18);return user;}@Beanpublic User user2(){User user = new User();user.setName("lisi");user.setAge(19);return user;}
}

定义了多个对象的话, 我们根据类型获取对象, 获取的是哪个对象呢?

@SpringBootApplication
public class SpringIocDemoApplication {public static void main(String[] args) {//获取Spring上下⽂对象ApplicationContext context = SpringApplication.run(SpringIocDemoApplication.class, args);//从Spring上下⽂中获取对象User user = context.getBean(User.class);//使⽤对象System.out.println(user);}
}

运行结果:
在这里插入图片描述

报错信息显示: 期望只有⼀个匹配, 结果发现了两个, user1, user2,从报错信息中, 可以看出来, @Bean 注解的 bean, bean 的名称就是它方法名

接下来我们根据名称来获取bean对象

@SpringBootApplication
public class SpringIocDemoApplication {public static void main(String[] args) {//获取Spring上下⽂对象ApplicationContext context = SpringApplication.run(SpringIocDemoApplication.class, args);//根据bean名称, 从Spring上下⽂中获取对象User user1 = (User) context.getBean("user1");User user2 = (User) context.getBean("user2");System.out.println(user1);System.out.println(user2);}
}

运行结果:
在这里插入图片描述
可以看到, @Bean 可以针对同⼀个类, 定义多个对象.

1.1.3 重命名 Bean

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

@Bean(name = {"u1","user1"})
public User user1(){User user = new User();user.setName("zhangsan");user.setAge(18);return user;
}

@Bean(name = {“u1”,“user1”}) 这一行是 @Bean 注解的一种变体,它不仅定义了一个Bean,还给这个 Bean 起了两个不同的名字,分别是 u1 和 user1。

此时我们使用 u1 就可以获取到 User 对象了,如下代码示:

@SpringBootApplication
public class SpringIocDemoApplication {public static void main(String[] args) {//获取Spring上下⽂对象ApplicationContext context = SpringApplication.run(SpringIocDemoApplication.class, args);//从Spring上下⽂中获取对象User u1 = (User) context.getBean("u1");//使⽤对象System.out.println(u1);}
}

1.2 扫描路径

使用前面学习的四个注解声明的 bean,⼀定会生效吗?答案是否定的,因为 bean 想要生效,还需要被 Spring 扫描

下⾯我们通过修改项目工程的目录结构,来测试 bean 对象是否生效:

在这里插入图片描述
再运行代码:

@SpringBootApplication
public class SpringIocDemoApplication {public static void main(String[] args) {//获取Spring上下⽂对象ApplicationContext context = SpringApplication.run(SpringIocDemoApplication.class, args);//从Spring上下⽂中获取对象User u1 = (User) context.getBean("u1");//使⽤对象System.out.println(u1);}
}

运行结果:

在这里插入图片描述

报错原因:没有 bean 的名称为u1,为什么没有找到 bean 对象呢?

原因是使用五大注解声明的 bean,要想生效, 还需要配置扫描路径, 让 Spring 扫描到这些注解,也就是通过 @ComponentScan 来配置扫描路径.

@ComponentScan({"com.example.demo"})
@SpringBootApplication
public class SpringIocDemoApplication {public static void main(String[] args) {//获取Spring上下⽂对象ApplicationContext context = SpringApplication.run(SpringIocDemoApplication.class, args);//从Spring上下⽂中获取对象User u1 = (User) context.getBean("u1");//使⽤对象System.out.println(u1);}
}

那为什么前⾯没有配置 @ComponentScan 注解也可以呢?

@ComponentScan 注解虽然没有显式配置,但是实际上已经包含在了启动类声明注解@SpringBootApplication 中了,默认扫描的范围是 SpringBoot 启动类所在包及其子包,在配置类上添加 @ComponentScan 注解, 该注解默认会扫描该类所在的包下所有的配置类

在这里插入图片描述
推荐做法:把启动类放在我们希望扫描的包的路径下, 这样我们定义的 bean 就都可以被扫描到

在这里插入图片描述

1.3 DI 详解

依赖注入是⼀个过程,是指 IoC 容器在创建 Bean 时, 去提供运行时所依赖的资源,而资源指的就是对象.

在上面程序案例中,我们使用了 @Autowired 这个注解,完成了依赖注入的操作,简单来说, 就是把对象取出来放到某个类的属性中.

关于依赖注入, Spring 也给我们提供了三种方式:

  1. 属性注入
  2. 构造方法注入
  3. Setter 注入

1.3.1 属性注入

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

  1. Service 类的实现代码如下:
import org.springframework.stereotype.Service;
@Service
public class UserService {public void sayHi() {System.out.println("Hi,UserService");}
}
  1. Controller 类的实现代码如下:
@Controller
public class UserController {//注⼊⽅法1: 属性注⼊@Autowiredprivate UserService userService;public void sayHi() {System.out.println("hi,UserController...");userService.sayHi();}
}
  1. 获取 Controller 中的 sayHi⽅法:
@SpringBootApplication
public class SpringIocDemoApplication {public static void main(String[] args) {//获取Spring上下⽂对象ApplicationContext context = SpringApplication.run(SpringIocDemoApplication.class, args);//从Spring上下⽂中获取对象UserController userController = (UserController) context.getBean("Controller");//使⽤对象userController.sayHi();}
}

最终结果如下:

在这里插入图片描述

去掉 @Autowired , 再运行一下程序看看结果

在这里插入图片描述

1.3.2 构造方法注入

构造方法注入是在类的构造方法中实现注入,如下代码所示:

@Controller
public class UserController2 {//注⼊⽅法2: 构造⽅法private UserService userService;@Autowiredpublic UserController2(UserService userService) {this.userService = userService;}public void sayHi(){System.out.println("hi,UserController2...");userService.sayHi();}
}

注意事项:如果类只有⼀个构造方法,那么 @Autowired 注解可以省略;如果类中有多个构造方法,那么需要添加上 @Autowired 来明确指定到底使用哪个构造方法。

1.3.3 Setter 注入

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

@Controller
public class UserController3 {//注⼊⽅法3: Setter⽅法注⼊private UserService userService;@Autowiredpublic void setUserService(UserService userService) {this.userService = userService;}public void sayHi(){System.out.println("hi,UserController3...");userService.sayHi();}
}

1.3.4 三种注入优缺点分析

第一种:属性注入

优点:

  • 简洁,使用方便

缺点:

  • 只能用于 IoC 容器,如果是非 IoC 容器不可用,并且只有在使用的时候才会出现 NPE(空指针异常)
  • 不能注入一个 Final 修饰的属性

第二种:构造函数注入 (Spring 4.X 推荐)

优点:

  • 可以注入 final 修饰的属性
  • 注入的对象不会被修改
  • 依赖对象在使用前一定会被完全初始化,因为依赖是在类的构造方法中执行的,而构造方法是在类加载阶段就会执行的方法。
  • 通用性好,构造方法是 JDK 支持的,所以更换任何框架都适用

缺点:

  • 注入多个对象时,代码会比较繁琐

第三种:Setter 注入 (Spring 3.X 推荐)

优点

  • 方便在类实例之后,重新对该对象进行配置或者注入

缺点:

  • 不能注入一个 Final 修饰的属性
  • 注入对象可能会被改变,因为 setter 方法可能会被多次调用,就有被修改的风险

1.3.5 @Autowired 存在问题

当同⼀类型存在多个 bean 时, 使⽤ @Autowired 会存在问题

@Component
public class BeanConfig {@Bean("u1")public User user1(){User user = new User();user.setName("zhangsan");user.setAge(18);return user;}@Beanpublic User user2() {User user = new User();user.setName("lisi");user.setAge(19);return user;}
}
@Controller
public class UserController {@Autowiredprivate UserService userService;//注⼊user@Autowiredprivate User user;public void sayHi(){System.out.println("hi,UserController...");userService.sayHi();System.out.println(user);}
}

运行结果:
在这里插入图片描述
报错的原因是,非唯⼀的 Bean 对象,如何解决上述问题呢?Spring 提供了以下几种解决方案:

  • @Primary
  • @Qualifier
  • @Resource

下面 一 一 进行讲解

  1. 使用 @Primary 注解:当存在多个相同类型的 Bean 注入时,加上 @Primary 注解,来确定默认的实现.
@Component
public class BeanConfig {@Primary //指定该bean为默认bean的实现@Bean("u1")public User user1(){User user = new User();user.setName("zhangsan");user.setAge(18);return user;}@Beanpublic User user2() {User user = new User();user.setName("lisi");user.setAge(19);return user;}
}
  1. 使用 @Qualifier 注解:指定当前要注入的 bean 对象。 在 @Qualifier 的 value 属性中,指定注入的 bean 的名称。

注意:@Qualifier 注解不能单独使用,必须配合 @Autowired 使用

@Controller
public class UserController {@Qualifier("user2") //指定bean名称@Autowiredprivate User user;public void sayHi(){System.out.println("hi,UserController...");System.out.println(user);}
}
  1. 使用 @Resource 注解:是按照 bean 的名称进行注入。通过 name 属性指定要注入的 bean 的名称。
@Controller
public class UserController {@Resource(name = "user2")private User user;public void sayHi(){System.out.println("hi,UserController...");System.out.println(user);}
}

@Autowird 与 @Resource 的区别

  • @Autowired 是 spring 框架提供的注解,而 @Resource 是 JDK 提供的注解

  • @Autowired 默认是按照类型注入,而 @Resource 是按照名称注入.

相比于 @Autowired 来说,@Resource 支持更多的参数设置,例如 name 设置,根据名称获取 Bean。

1.4 总结

Spring, Spring Boot 和 Spring MVC 的关系以及区别:

  1. Spring:

简单来说, Spring 是⼀个开发应用框架,目的是用于简化企业级应用程序开发.

  1. Spring MVC:

Spring MVC 是 Spring 的⼀个子框架, Spring 诞生之后, 大家觉得很好用, 于是按照MVC模式设计了⼀个 MVC 框架,用于开发 web 应用和网络接口。

  1. Spring Boot:

Spring Boot 是对 Spring 的⼀个封装, 为了简化 Spring 用的开发而出现的,中小型企业,没有成本研究自己的框架, 使用 Spring Boot 可以更加快速的搭建框架, 降级开发成本, 让开发人员更加专注于 Spring 应用的开发,而无需过多关注 XML 的配置和⼀些底层的实现.

Spring, Spring Boot 和 Spring MVC 的功能:

  1. Spring

spring 主要用于管理对象和对象之间的依赖关系

  1. Spring MVC

基于 Spring 进行开发的, 天生的与 Spring 框架集成. 可以让我们更简洁的进行 Web 层开发, 支持灵活的 URL 到页面控制器的映射

  1. Spring Boot

Spring Boot 是个脚手架, 插拔式搭建项⽬, 可以快速的集成其他框架进来,比如想使用SpringBoot 开发 Web 项目, 只需要引入 Spring MVC 框架即可

  1. ⼀句话总结

Spring MVC 和 Spring Boot 都属于 Spring,Spring MVC 是基于 Spring的⼀个MVC 框架,而 Spring Boot 是基于 Spring 的⼀套快速开发整合包.

比如我们的图书系统代码中:

  • 整体框架是通过 SpringBoot 搭建的
  • IoC, DI 功能是 Spring 的提供的,
  • web 相关功能是 Spring MVC 提供的

这三者专注的领域不同,解决的问题也不⼀样, 总的来说,Spring 就像⼀个大家族,有众多衍生产品, 但他们的基础都是 Spring

在这里插入图片描述

在这里插入图片描述

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

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

相关文章

Unity 踩坑记录 Rigidbody 刚体重力失效

playerSetting > physics > Gravity > 设置 Y 的值为负数

前端canvas项目实战——在线图文编辑器(九):逻辑画布

目录 前言一、 效果展示二、 实现步骤1. 调整布局,最大化利用屏幕空间2. 添加逻辑画布3. 添加遮罩4. 居中显示逻辑画布5. 一个容易被忽视的bug点 三、Show u the code后记 前言 上一篇博文中,我们实现了一组通用的功能按钮:复制、删除、锁定…

FreeRTOS之列表

1.FreeRTOS的列表和列表项十分重要。列表类相当于链表,列表项则相当于链表中的节点。列表项的地址是非连续的,列表项的数量可随时修改。在OS中的任务状态和数量会发生改变,因此使用列表可以很好的满足需求。 列表和列表项的相关定义与操作函…

电商独立站||跨境电商独立站网站搭建|功能系统搭建||API接口接入

搭建多语言跨境电商独立站系统 前台主要功能模块 短信接口 第三方登陆 支付方式 会员中心 代购订单列表 - new 会员签到 -1000(1) new 支付密码 ---1000 国内流程 -----5000 new 订单运单多退少补 -1000 未付款运单取消功能 - 修改运单运输方式 -----1000 年费会员 -----3000 …

大型零售企业,适合什么样的企业邮箱大文件解决方案?

大型零售企业通常指的是在全球或特定地区内具有显著市场影响力和知名度的零售商。这些企业不仅在零售业务收入上达到了惊人的规模,而且在全球范围内拥有广泛的销售网络和实体店铺。它们在快速变化的零售行业中持续创新,通过实体店、电商平台等多种渠道吸…

C#队列(Queue)的基本使用

概述 在编程中&#xff0c;队列&#xff08;Queue&#xff09;是一种常见的数据结构&#xff0c;它遵循FIFO&#xff08;先进先出&#xff09;的原则。在C#中&#xff0c;.NET Framework提供了Queue<T>类&#xff0c;它位于System.Collections.Generic命名空间下&#x…

【深度学习实战(26)】标签处理之语义分割标签转换,数据集划分

一、标签转换 我们在使用labeme标签工具&#xff0c;标注完数据后会获得json文件。在标注结束过后&#xff0c;我们需要通过标签转换操作&#xff0c;生成jpg格式原始图片和png格式mask标签图。 1.1 使用img_b64_to_arr将json标签中二进制图像数据变成numpy格式数据&#xf…

selenium在Pycharm中结合python的基本使用、交互、无界面访问

下载 下载与浏览器匹配的浏览器驱动文件&#xff0c;这里一定注意的是&#xff0c;要选择和浏览器版本号相同的驱动程序&#xff0c;否则后面会有很多问题。 &#xff08;1&#xff09;浏览器&#xff08;以google为例&#xff09;版本号的查询&#xff1a; 我这里的版本号是1…

java实现模板填充word,word转pdf,pdf转图片

Java实现Word转PDF及PDF转图片 在日常开发中&#xff0c;我们经常需要将文件操作&#xff0c;比如&#xff1a; 根据模板填充wordword文档中插入图片Word文档转换为PDF格式将PDF文件转换为图片。 这些转换可以帮助我们在不同的场景下展示或处理文档内容。下面&#xff0c;我将…

Leetcode—1256. 加密数字【中等】Plus(bitset、find_first_not_of、erase)

2024每日刷题&#xff08;120&#xff09; Leetcode—1256. 加密数字 实现代码 class Solution { public:string encode(int num) {string ans;num 1;while(num ! 0) {ans to_string(num & 1);num num >> 1;}if(ans.empty()) {return "";} else {stri…

coreldraw2024精简版绿色版安装包免费下载

CorelDRAW 2024是一款矢量图形设计软件&#xff0c;于2024年3月5日正式在全球范围内发布。这款软件在多个方面进行了更新和改进&#xff0c;为用户提供了更多高效、灵活和便捷的设计工具。 首先&#xff0c;CorelDRAW 2024新增了绘画笔刷功能&#xff0c;这些笔刷不仅模拟了传…

Ubuntu20.04 [Ros Noetic]版本——在catkin_make编译时出现报错的解决方案

今天在新的笔记本电脑上进行catkin_make的编译过程中遇到了报错&#xff0c;这个报错在之前也遇到过&#xff0c;但是&#xff0c;我却忘了怎么解决。很是头痛&#xff01; 经过多篇博客的查询&#xff0c;特此解决了这个编译报错的问题&#xff0c;于此特地记录&#xff01;&…

[论文笔记]SEARCHING FOR ACTIVATION FUNCTIONS

引言 今天带来另一篇激活函数论文SEARCHING FOR ACTIVATION FUNCTIONS的笔记。 作者利用自动搜索技术来发现新的激活函数。通过结合详尽的搜索和基于强化学习的搜索&#xff0c;通过实验发现最佳的激活函数 f ( x ) x ⋅ sigmoid ( β x ) f(x) x \cdot \text{sigmoid}(βx…

瓦片编辑器成功移植到小熊猫C++ 2.25.1版本,解决_findnext移植问题

移植之后出现绿色屏幕闪退 查了版本回滚直到不闪退&#xff0c;发现是在读取自定义文件上出问题 然后在找读取自定义文件函数&#xff0c;发现是读取图片部分出问题 然后就卡住了 调试半天&#xff0c;不是数据溢出&#xff0c;于是就看 函数_findnext,网上搜 ———_findn…

4.Docker本地镜像发布至阿里云仓库、私有仓库、DockerHub

文章目录 0、镜像的生成方法1、本地镜像发布到阿里云仓库2、本地镜像发布到私有仓库3、本地镜像发布到Docker Hub仓库 Docker仓库是集中存放镜像的地方&#xff0c;分为公共仓库和私有仓库。 注册服务器是存放仓库的具体服务器&#xff0c;一个注册服务器上可以有多个仓库&…

项目开发规范

Restful REST&#xff0c;表述性状态转换&#xff0c;他是一种软件架构风格 使用URL定位资源&#xff0c;HTTP动词描述操作 根据发出请求类型来区分操作 GET&#xff1a; 查询id为1的用户POST&#xff1a;新增用户PUT&#xff1a;修改用户DELETE&#xff1a;删除id为1的用户 …

springboot权限验证学习-上

创建maven项目 创建父工程 这类项目和原来项目的区别在于&#xff0c;打包方式是pom 由于pom项目一般都是用来做父项目的&#xff0c;所以该项目的src文件夹可以删除掉。 创建子工程 子工程pom.xml 父工程pom.xml 添加依赖 父工程导入依赖包 <!--导入springboot 父工程…

18.Nacos配置管理-微服务读取Nacos中的配置

需要解决的问题 1.实现配置更改热更新&#xff0c;而不是改动了配置文件还要去重启服务才能生效。 2.对多个微服务的配置文件统一集中管理。而不是需要对每个微服务逐一去修改配置文件&#xff0c;特别是公共通用的配置。 配置管理服务中的配置发生改变后&#xff0c;回去立…

病理组学+配对 mIHC 验证+转录组多组学

目录 病理DeepRisk网络模型构建 DPS和新辅助化疗 mIHC 验证 STAD转录组层面 病理DeepRisk网络模型构建 自有数据训练&#xff0c;TCGA数据进行验证&#xff0c;然后配对mIF验证&#xff0c;最后还在转录组层面分析。 该模型基于中山数据集&#xff08;n 1120&#xff09…

【AIGC调研系列】Sora级别的国产视频大模型-Vidu

Vidu能够达到Sora级别的标准。Vidu被多个来源认为是国内首个Sora级别的视频大模型[2][3][4]。它采用了团队原创的Diffusion与Transformer融合的架构U-ViT&#xff0c;能够生成长达16秒、分辨率高达1080P的高清视频内容[1][6]。此外&#xff0c;Vidu的一致性、运动幅度都达到了S…