Spring IOCDI

1. 什么是Spring

前面介绍了Spring Boot,Spring MVC,那么Spring和他们之间有什么关系呢?

Spring简单一句话总结就是:它是一个包含众多工具方法的IOC容器。前面我们也接触过容器,比如List/Map,他俩是数据存储容器。

2. IOC

前面介绍了@RestController和@Controller。这两个注解修饰的类会交给Spring来管理,Sping启动的时候这些类(对象)就会被加载,把对象交给Spring来管理就是IOC。

IOC的全称:Inversion of Control (控制反转), 也就是说 Spring 是⼀个"控制反转"的容器。这个控制反转其实应该是控制权反转。那么是什么控制权反转呢?以前创建对象需要自己new,现在把控制权交给Spring,Spring来帮助我们创建对象,我们想使用对象时直接DI (依赖注⼊Dependency Injection)。由此创建对象和使用对象都只需要跟Spring容器交互,由此降低了他们之间的耦合程度。

2.1. IOC容器的优点

1. 资源集中管理:资源不由使用资源的两方管理,而是由不使用资源的第三方管理,要使用资源只需要去IOC容器当中获取就可以。

2. 降低耦合程度:创建实例的时候不需要了解其中的细节,降低了使用资源双方的依赖程度,也就是降低了耦合程度。

下面通过一个项目来综合练习一下

2.2. Bean的存储 

存储Bean共有两类注解:

1. 类注解:@Controller、@Service、@Repository、@Component、@Configuration.
2. 方法 注解:@Bean.
在编写代码的过程中我们会把代码分层,分为三层,控制层,业务逻辑层,数据访问层
1. Controller:控制层,负责接收前端发送的数据,对请求进行处理,返回响应。
2. Service:业务逻辑层,负责业务逻辑处理,比如处理用户发来的请求。
3. Dao:数据访问层,也称为持久层,负责执行CRUD语句
Service和Dao层的实现类交给Spring来管理,使用:@Component;
Service和Controller层注入运行时依赖的对象,使用:@Autowired。

2.3. @Controller(控制器存储)

ok,现在已经把这个对象存储到Spring当中了,前面说到Spring是一个容器,如何看这个对象是否真的被存进去了呢? 

@SpringBootApplication
public class DemoApplication {public static void main(String[] args) {//获取Spring上下⽂对象ApplicationContext context = SpringApplication.run(DemoApplicatio)//从Spring上下⽂中获取对象MyController controller = context.getBean(MyController.class);//使⽤对象controller.sayHi();}}

运行后可以看到结果 

上面使用的是按类型查找对象,那么如果一个类型有多个Bean该怎么获取呢?

public interface BeanFactory {// 1. 根据bean名称获取beanObject getBean(String var1) throws BeansException;// 2. 根据bean名称和类型获取bean<T> T getBean(String var1, Class<T> var2) throws BeansException;// 3. 按bean名称和构造函数参数动态创建bean,只适⽤于具有原型(prototype)作⽤域的beanObject getBean(String var1, Object... var2) throws BeansException;// 4. 根据类型获取bean<T> T getBean(Class<T> var1) throws BeansException;// 5. 按bean类型和构造函数参数动态创建bean, 只适⽤于具有原型(prototype)作⽤域的bean<T> T getBean(Class<T> var1, Object... var2) throws BeansException;}

常用的是1,2,4 这三种方法获取到的bean是一样的。1和2都涉及到bean的名称。那么这bean名称是随便命名的吗?

2.4. Bean的命名方式

Spring bean是Spring框架在运行时管理的对象,Spring会给bean起一个名字。就像学生在学校都会有学号,学校只需要查找学号就能知道学生的身份信息。Spring也会给这些bean取一个对象名(beanId),通过beanId就能找到bean。我们开发人员不必自己进行命名,Spring会自动进行命名:比如存入的bean的名字:MyController,Spring命名会变成myController,也就是首字母小写的驼峰式大小写;特殊情况,如果首字母和第二个字母都是大写,那么Spring会直接使用bean的名字例子:UController,命名后:UController。

2.5. 获取bean

//!!注意:如果遇到contex.getBean,点不出来的的时候要看看导的包对不对!!
import com.example.demo.demos.web.Controller.MyController;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;@SpringBootApplication
public class DemoApplication {public static void main(String[] args) {ApplicationContext context =SpringApplication.run(DemoApplication.class, args);//根据类型获取beanMyController myController1 = context.getBean(MyController.class);//根据名称获取beanMyController myController2 = (MyController)context.getBean("myController");//根据类型和名称获取beanMyController mycontroller3 = context.getBean("myController",MyController.class);System.out.println("根据类型获取bean:" + myController1);System.out.println("根据名称获取bean:" + mycontroller3);System.out.println("根据名称和类型获取bean:" + myController2);}
}

2.6. ApplicationContext和BeanFactory的区别? 

1. 从继承和功能上来看:Spring容器有两个顶级的接口:ApplicationContext和BeanFactroy。BeanFactory提供了最基本的访问容器的能力,而ApplicationContext继承了BeanFactory,所以包含BeanFactory的所有功能,但是增加了国家化支持,资源访问支持等。

2. 从性能方面来说:ApplicationContext会初始化并加载所有bean,BeanFactory是需要哪个bean才会加载哪个,所以BeanFactory的性能更高(空间换时间)。

2.7. @Service(服务存储)

@SpringBootApplication
public class DemoApplication {public static void main(String[] args) {ApplicationContext context =SpringApplication.run(DemoApplication.class, args);//按名称获取UserService service1 = (UserService)context.getBean("userService");//按类型获取UserService service2 = context.getBean(UserService.class);//按类型和名称获取UserService service3 = context.getBean("userService",UserService.class);System.out.println("1:"+service1);service1.sayHi();System.out.println("2:"+service2);System.out.println("3:"+service3);}
}

还有:@Repositary (仓库存储),@Configuration(配置存储),@Component(组件存储),代码上都是一样的,不再一 一展示。

2.8. 这五个类注解的作用是什么?

@Controller:控制层,负责与前端进行交互(接收前端发送的数据,把数据传回给前端)。

@Service:业务逻辑层,负责处理前端发送来的数据或者请求。

@Repository:持久层,负责与数据库进行交互。

@Configuration:配置层,包含项目中的一些配置信息。

这四个注解让人很直观的能看出来是做什么用的。

那还有一个注解:@Component呢?

先来看一下@Controller注解的底层代码,可以发现包含@Component,上面剩下三个注解底层也都包含这个注解,不一 一展示了。说面这四个注解是@Component的 “子类”,@Component属于元注解,也就是说它可以注解其他类注解,剩下四个注解属于它的衍生注解。

举个例子:@Component类似于杯子,而喝水时我们通常使用水杯,刷牙时通常使用牙杯。水杯和牙杯就是@Controller等注解。

2.9. 方法注解@Bean

类注解有两个问题:

1. 想使用不同包下的类无法使用类注解。

2.一个类需要多个对象,需要多个数据源无法使用类注解。

下面来演示一下,注意@Bean需要搭配方法注解使用!!

 2.10. 定义多个对象

所以,当有多个相同类型的对象时不能使用按类型查找,要使用按类型和名称查找和按名称查找,演示用的是按类型和名称。

 2.11. 给bean重命名

 此时使用u1和user1都可以获取到。

只有一个名称的时候大括号也可以省略不写

 3. Di

上面介绍了控制反转,也就是IOC,下面介绍一下DI,DI是依赖注入,简单来说就是把对象取出来放到某个类的属性当中。

依赖注入有三种方式:

1. 属性注入;

2. 构造方法注入;

3. Setter方法注入。

3.1 属性注入

3.2 构造方法注入 

3.3 setter方法注入 

3.4 三种注入方法的优缺点是什么? 

1. 属性注入

优点:代码简单

缺点:

1. 只能用于IOC容器,只有在使用过程中才会出现NPE(空指针异常)

2. 不能注入一个final修饰的属性

2. 构造方法注入(Spring 4.X时推荐)

优点:

1. 可以注入一个final修饰的属性。

2. 注入的依赖对象不能被改变

3. 依赖对象在使用前一定会被完全初始化,因为依赖是在类的构造方法中执行的,而构造方法是类在加载阶段就会完成的方法。

4. 通用性好,因为构造方法是JDK所支持的,其他任何框架都能适用。

缺点:多个对象注入的时候代码繁琐。

3. Setter方法注入(Spring 3.X时推荐)

优点:方便在类实例化之后,重新对该对象进行配置或注入。

缺点:

1. 不能注入一个final修饰的属性。

2. 注入对象可能会被修改,因为setter方法可能会被多次调用。

3.5 @Autowired存在的问题

可以看到,当有多个相同类型的对象时再使用@Autowried注解就不好用了。

为了解决这个问题,下面再引入三个注解:@Primary,@Qualifier,@Resource

@Primary注解放到某个@Bean修饰的注解上时意味着默认注入该对象。

@Qualifier注解不能单独使用,必须搭配@Autowired使用,可以指定bean的名称注入

@Resource注解支持很多,也可以指定bean名称注入,但是不用必须搭配@Autowired。

3.6 @Autowired和@Resource的区别

1. @Autowired是Spring提供的注解,@Resource是JDK提供的注解。

2. @Autowired按类型注入,@Resource按名称注入,并且@Resource支持很多种注入方式。

 4.图书管理项目

根据前面的介绍,做一个综合练习。

可以看到Controller层创建了两个class文件。还创建了一堆html,css,JS(JavaScript)文件。这些都是前端文件,前端文件统一放在static包下,html文件中主要在写一个网页页面有哪些内容,以及业务逻辑,css是对html中声明的内容进行美化,比如html中编写了“你好”这两个字,css可以改变你好这两个字的大小,颜色等等。

如果需要这些源文件的可以在评论区留言,如果没人看这篇博客笔者也没必要花时间弄链接,笔者写博客是为了归纳总结已学习过的知识。

下面是后端代码

//BookController代码:import com.example.demo.demos.web.BookInfo;
import com.example.demo.demos.web.Service.BookService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;import java.util.List;@RequestMapping("/book")
@RestController
public class bookController {@Autowiredprivate BookService bookService;@RequestMapping("/getList")public List<BookInfo> getList(){List<BookInfo> books = bookService.getBook();return books;}
}
//UserController代码:负责登录验证@RequestMapping("/user")
@RestController
public class UserController {@RequestMapping("/login")public Boolean login(String name, String password, HttpSession session){if(!StringUtils.hasLength(name) || !StringUtils.hasLength(password)){return false;}if("1".equals(name) && "1".equals(password)){session.setAttribute("userName",name);return true;}return false;}
}
import com.example.demo.demos.web.BookInfo;
import org.springframework.stereotype.Repository;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;@Repository
public class BookDao {public List<BookInfo> mockData() {List<BookInfo> bookInfos = new ArrayList<>();for (int i = 0; i < 5; i++) {BookInfo book = new BookInfo();book.setId(i);book.setBookName("书籍" + i);book.setAuthor("作者" + i);book.setCount(i * 5 + 3);book.setPrice(new BigDecimal(new Random().nextInt(100)));book.setPublish("出版社" + i);book.setStatus(1);bookInfos.add(book);}return bookInfos;}
}
import com.example.demo.demos.web.BookInfo;
import com.example.demo.demos.web.Dao.BookDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;import java.util.List;
@Service
public class BookService {@Autowiredprivate BookDao bookDao;public List<BookInfo> getBook(){List<BookInfo> books = bookDao.mockData();for (BookInfo bookInfo:books) {if(bookInfo.getStatus() == 1){bookInfo.setStatusCN("可借阅");}else {bookInfo.setStatusCN("不可借阅");}}return books;}
}
效果展示:

可以看到这个项目还是很简陋的,正常验证用户密码和用户名是否匹配和书籍信息都是应该要去数据库中查找的,但是这些内容现在的知识是没办法实现的,后面随着笔者介绍MyBatis框架之后就可以把数据库相关操作加入进来。

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

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

相关文章

螺旋矩阵II(leetcode 59)

转圈过程&#xff08;边界处理&#xff09;遵循循环不变量的原则&#xff0c;坚持一个原则处理每一条边&#xff0c;左闭右开处理 class Solution { public:vector<vector<int>> generateMatrix(int n) {vector<vector<int>> num(n, vector<int>…

Vue 中的透传,插槽,依赖注入

1. 透传attributes 在组件上使用透传attribute&#xff1a; 当你在父组件中使用子组件时&#xff0c;你可以添加一些attribute到子组件上&#xff0c;即使这些attribute没有在子组件的props中声明。 父组件&#xff1a; <!-- 父组件&#xff0c;例如 ParentComponent.vue…

基于K8S1.28.2实验rook部署ceph

基于K8S1.28.2实验rook部署ceph 原文链接&#xff1a; 基于K8S1.28.2实验rook部署ceph | 严千屹博客 Rook 支持 Kubernetes v1.22 或更高版本。 rook版本1.12.8 K8S版本1.28.2 部署出来ceph版本是quincy版本 主机名ip1(NAT)系统新硬盘磁盘内存master1192.168.48.101Centos7.910…

node.js中express的基本了解

定义 Express是基于Node.js平台&#xff0c;快速、开放、极简的Web开发框架。 本质 Express是一个npm上的第三方包&#xff0c;提供了快速创建Web服务器的便捷方法。 作用 与Node.js内置的http模块类似&#xff0c;Express也是专门用来创建Web服务器的&#xff0c;但它极大地简…

容器运行时 AND Docker

容器运行时 and Docker 什么是Docker Docker 使用 Google 公司推出的 Go 语言 进行开发实现&#xff0c;基于 Linux 内核的 cgroup&#xff0c;namespace&#xff0c;以及 AUFS 类的 Union FS 等技术&#xff0c;对进程进行封装隔离&#xff0c;属于 操作系统层面的虚拟化技术…

基于Python深度学习的【垃圾识别系统】实现~TensorFlow+人工智能+算法网络

一、介绍 垃圾识别分类系统。本系统采用Python作为主要编程语言&#xff0c;通过收集了5种常见的垃圾数据集&#xff08;‘塑料’, ‘玻璃’, ‘纸张’, ‘纸板’, ‘金属’&#xff09;&#xff0c;然后基于TensorFlow搭建卷积神经网络算法模型&#xff0c;通过对图像数据集进…

Scala-数据类型-概述(Scala 3.x 类型层次结构)

Scala Scala-数据类型 Scala1. Any — 顶级类型2. Matchable — 匹配类型3. AnyVal — 值类型的父类4. AnyRef — 引用类型的父类5. Null - 引用类型的子类型Tips: 为什么 null 不推荐使用&#xff1f; 6. Nothing - 底层类型 (Bottom Type)整理不易&#xff0c;对您有帮助的话…

Linux:权限相关知识详解

1.shell命令以及运行原理 1.1初步理解认识shell Linux严格意义上说的是一个操作系统&#xff0c;我们称之为“核心&#xff08;kernel&#xff09;“ &#xff0c;但我们一般用户&#xff0c;不能直接使用kernel。而是通过kernel的“外壳”程序&#xff0c;也就是所谓的shell&…

React中常用的钩子

在当今&#xff0c;React的钩子写法已经逐渐成为了一种主流开发模式&#xff0c;本文将介绍几种在React中常用的钩子 useState 可以用来双向绑定&#xff0c;创建需要监听变化并且使用的数据 使用该钩子定义时&#xff0c;参数可以是一个直接定义好的变量&#xff0c;也可以是…

.NET SDK 各操作系统开发环境搭建

一、Win10&#xff08;推荐&#xff09; 1、VS 2022 社区版 # 下载地址 https://visualstudio.microsoft.com/zh-hans/downloads/ 2、.NET 6 SDK # 下载地址 https://dotnet.microsoft.com/zh-cn/download/dotnet/6.0 3、Hello World 如果需要使用旧程序样式时&#xff0c;则…

Linux 下网络套接字(Socket) 与udp和tcp 相关接口

文章目录 1. socket常见API2 sockaddr结构体及其子类1. sockaddr结构体定义&#xff08;基类&#xff09;2. 子类 sockaddr_in结构体用于(IPv4)3 子类 sockaddr_un(Unix域套接字)4. 总结画出其结构体 3.实现一个简单的tcp Echo 服务器和客户端(cpp&#xff09;3.1 客户端3.2 服…

跨平台WPF框架Avalonia教程 七

数据绑定 Avalonia使用数据绑定将数据从应用程序对象传递到UI控件&#xff0c;根据用户输入更改应用程序对象中的数据&#xff0c;并在响应用户命令时对应用程序对象进行操作。 在这种安排中&#xff0c;控件是绑定目标&#xff0c;而对象是数据源。 Avalonia运行数据绑定系统…

日常ctf

1&#xff0c; [陇剑杯 2021]日志分析&#xff08;问1&#xff09; %2e 为URL编码的符号 "." flag{www.zip} 2&#xff0c; [陇剑杯 2021]日志分析&#xff08;问2&#xff09; 根据之前题目的分析&#xff0c;在获取到源码文件之后&#xff0c;黑客又成功访问了in…

基于微信小程序的校园助手+LW示例参考

1.项目介绍 项目角色&#xff1a;管理员、普通用户功能模块&#xff1a;管理员&#xff08;用户管理、寻物启事管理、物品分类管理、表白广场、吐槽大会、二手交易、拼车出行等&#xff09;、普通用户&#xff08;登录注册、寻物启事、失物招领、表白广场、吐槽大会、拼车出行…

逆向攻防世界CTF系列38-xxxorrr

逆向攻防世界CTF系列38-xxxorrr 64位无壳&#xff0c;很自然的找到main和一个比较函数 以为逻辑很简单了 enc [0x56, 0x4E, 0x57, 0x58, 0x51, 0x51, 0x09, 0x46, 0x17, 0x46,0x54, 0x5A, 0x59, 0x59, 0x1F, 0x48, 0x32, 0x5B, 0x6B, 0x7C,0x75, 0x6E, 0x7E, 0x6E, 0x2F, 0…

数据结构-堆排序笔记

1 思路 总体思路 首先我们会拿到一个无序的数组&#xff0c;我们需要先对其构建成一个堆。下面我们示例将会构建成大顶堆。然后我们对顶堆的元素进行位置之间的交换。交换的同时继续对其维护大顶堆的性质&#xff0c;直至大顶堆只剩下一个元素。 具体思路 首先我们先将一个…

如何在react中使用react-monaco-editor渲染出一个编辑器

一、效果展示 二、基于vite配置 1.首先安装react-monaco-editor和monaco-editor包 npm add react-monaco-editor npm i monaco-editor 2.其次创建一个单独的文件&#xff08;此处是tsx、直接用app或者jsx也行&#xff09; import { useState, useEffect } from react impo…

跨平台WPF框架Avalonia教程 六

添加交互性 用户界面的一个基本功能是与用户进行交互。在Avalonia中&#xff0c;您可以通过使用事件和命令来为应用程序添加交互性。本指南将通过简单的示例介绍事件和命令。 处理事件​ Avalonia中的事件提供了一种响应用户交互和控件特定操作的方式。您可以按照以下步骤处…

【传知代码】VRT_ 关于视频修复的模型

&#x1f4dd;个人主页&#x1f339;&#xff1a;Eternity._ &#x1f339;&#x1f339;期待您的关注 &#x1f339;&#x1f339; ❀ VRT_ 关于视频修复的模型 背景介绍&#xff1a;重要性&#xff1a; VRT的重要性和研究背景VRT的背景&#xff1a;VRT的重要性&#xff1a; 视…

药界互联:中药实验管理的网络化

摘要 随着信息技术在管理上越来越深入而广泛的应用&#xff0c;管理信息系统的实施在技术上已逐步成熟。本文介绍了中药实验管理系统的开发全过程。通过分析中药实验管理系统管理的不足&#xff0c;创建了一个计算机管理中药实验管理系统的方案。文章介绍了中药实验管理系统的系…