Spring两大核心思想 IoC和AoP

目录

✨ 一、什么是IoC

1、定义 🎊

2、IoC思想 🎊

3、优势 🎊

4、对象的管理 🎊

存对象:@Component

取对象:@AutoWired 

✨二、什么是DI 

1、定义 🎊

2、IoC和DI的关系🎊

可以说DI是IoC的一种实现

✨三、IoC&DI的使用 

1、实现实例:用@Component注解实现存 🎊

2、 使用@AutoWired注解实现从容器中取对象🎊

✨四、IoC详解 

1、Bean的存储(类注解)🎊

1) @Controller(控制器存储)(控制层,接受请求,对请求进行处理,并进行响应)

从容器中获取对象:Spring上下文

2)@Service(服务存储)(业务逻辑层,处理具体的业务逻辑) 

​编辑 

3)Repository(仓库存储)(数据访问层,也称为持久层,负责数据的访问操作)

4)Component(组件存储)

5)Configuration(配置存储)(配置层,处理项目中的一些配置信息)

 2、Bean的命名🎊

 3、获取bean对象的方法(是父类(BeanFactory)提供的功能)🎊

常见的面试题: ApplicationContext VS BeanFactory

 4、方法注解(@Bean)🎊

1、一个对象的情况 

2、多个对象的情况 

 3、重命名Bean

5、扫描路径🎊

✨五、DI详解 

1、依赖注入的三种方法 🎊

1)属性注入(Field Injection)Autowired

2) 构造方法注入(Constructor Injection)

3)Setter注入(Setter Jniection)

2、三种注入的优缺点分析 🎊

3、@Autowired存在问题(当同一类型存在多个bean时)🎊


让我们先回顾一下什么是Spring:Spring是一个开源框架,他让我们的开发更简单,简单来说,Spring是包含了众多工具的IoC容器。

那么问题来了,什么是容器?什么是IoC容器?

容器是用来容纳某种物品的(基本)装置

  • List/Map ->数据存储器
  • Tomact -> Web容器

 一、什么是IoC

1、定义 

  Inversion of Control(控制反转),也就是说“Spring”是一个控制反转容器。

当需要某个对象时,传统的开发模式中需要new来创建对象,现在不需要再进行创建了,把创建对象的任务交给容器,由Spring来负责对象的创建和销毁,程序只需要依赖注入(Dependency Injection,DI) 就可以了。

这个容器称为:IoC容器。Spring是一个IoC容器,有时候Spring也称为Spring容器。(容器里面装的是对象,Spring管理的对象称之为bean

2、IoC思想 

     像我们之前写代码,在类上面添加@RestController和@Controller注解,就是把这个对象交给Spring来管理,Spring框架启动时就会加载该类,把对象交给Spring管理,就是IoC思想。 

3、优势 

资源不由使用资源的双方管理,而由不使用资源的第三方管理。

  1. 资源集中管理:IoC容器会帮我们管理一些资源(对象等),需要时,只需要从IoC容器中去取就可以了
  2. 我们在创建实例的时候不需要了解其中的细节,降低了使用资源双方的依赖程度,也就是耦合度。 

4、对象的管理 

  1. 存对象:@Component

  2. 取对象:@AutoWired 

二、什么是DI 

1、定义 

 Dependency Injection,DI(依赖注入),容器在运行期间,动态的为应用程序提供运行时所依赖的资源,称之为依赖注入。

2、IoC和DI的关系

可以说DI是IoC的一种实现

可以看出,依赖注入和控制反转是从不同的角度的描述同一件事情,就是指通过引入IoC容器,利用依赖关系注入的方式,实现对象之间的解耦。 

三、IoC&DI的使用 

1、实现实例:用@Component注解实现存 

@Component
public class BookDao {public List<BookInfo> mockBookData() {List<BookInfo> bookInfos = new ArrayList<>();for(int i = 1;i < 15; i++) {BookInfo bookInfo = new BookInfo();bookInfo.setId(i);bookInfo.setBookName("图书" + i);bookInfo.setAuthor("作者" + i);bookInfo.setCount(i*15 + 3);bookInfo.setPrice(new BigDecimal(new Random().nextInt(100)));bookInfo.setPublish("出版社" + i);bookInfo.setStatus(i%5==0?2:1);bookInfos.add(bookInfo);}return bookInfos;}
}
@Component
public class BookService {/*** 根据数据层返回的结果对数据进行处理* @return*///从Spring中获取对象@Autowiredprivate BookDao bookDao;public List<BookInfo> bookInfoList(){List<BookInfo> bookInfos = bookDao.mockBookData();for(BookInfo bookInfo: bookInfos) {if(bookInfo.getStatus()==1) {bookInfo.setStateCN("可借阅");}else if(bookInfo.getStatus()==2){bookInfo.setStateCN("不可借阅");}}return bookInfos;}
}

2、 使用@AutoWired注解实现从容器中取对象

@Autowiredprivate BookDao bookDao;

四、IoC详解 

1、Bean的存储(类注解)

通过前面 学习,我们知道了把某个对象交给IoC容器进行管理,需要在类上添加一个注解,而Spring也提供了更丰富的注解。

类注解:@Controller、@Service(服务存储)、@Component(组件存储)、@Repository(仓库存储)、@Configuration(配置存储)

方法注解:@Bean

设置这么多类注解目的是为了让程序员看到类注解之后,就直接了当的了解当前类的用途

1) @Controller(控制器存储)(控制层,接受请求,对请求进行处理,并进行响应)

看下面例子:使用 @Controller存储bean的代码

package com.example.example1.controller;import org.springframework.stereotype.Controller;@Controller
public class UserController {public void sayHi() {System.out.println("祝你好运,小李");}
}

如何观察这个对象已经存在在Spring容器中了呢?

@SpringBootApplication
public class Example1Application {public static void main(String[] args) {//获取Spring上下文对象ApplicationContext context = SpringApplication.run(Example1Application.class, args);//从Spring上下文中获取对象UserController userController = context.getBean(UserController.class);//使用对象userController.sayHi();}}

运行程序: 

但如果删除@Controller,观察运行结果: 

 

从容器中获取对象:Spring上下文

 上下文:就是指当前的运行环境,也可以看做是一个容器,容器里面存了很多内容,这些内容是当前的运行的环境。

ApplicationContext context = SpringApplication.run(Example1Application.class, args);

2)@Service(服务存储)(业务逻辑层,处理具体的业务逻辑) 

package com.example.example1.service;import org.springframework.stereotype.Service;@Service
public class UserService {public void sayHi() {System.out.println("祝你幸福快乐,小李");}
}
  //获取Spring上下文对象ApplicationContext context = SpringApplication.run(Example1Application.class, args);       UserService userService = context.getBean(UserService.class);userService.sayHi();

 

3)Repository(仓库存储)(数据访问层,也称为持久层,负责数据的访问操作)

4)Component(组件存储)

5)Configuration(配置存储)(配置层,处理项目中的一些配置信息)

 2、Bean的命名

程序开发人员不需要为bean指定名称 ,如果没有显示的提供名称,Spring容器将为该Bean生成唯一的名称

来看spring官方文档中说明:Bean Overview :: Spring Framework

 

 3、获取bean对象的方法(是父类(BeanFactory)提供的功能)

package com.example.example1;import com.example.example1.controller.UserController;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;@SpringBootApplication
public class Example1Application {public static void main(String[] args) {//获取Spring上下文对象ApplicationContext context = SpringApplication.run(Example1Application.class, args);//从Spring上下文中获取对象,根据类型UserController userController1 = context.getBean(UserController.class);//根据名称UserController userController2 = (UserController) context.getBean("userController");//根据类型+名称UserController userController3 = context.getBean("userController", UserController.class);System.out.println(userController1);System.out.println(userController2);System.out.println(userController3);}}

 

常见的面试题: ApplicationContext VS BeanFactory

  • 继承关系和功能方面来说:Spring容器有两个顶级的接口:BeanFactory和ApplicationContext。其中前者提供了基础的访问容器的能力,后者属于 BeanFactory的子类,他除了继承了BeanFactory的所有功能之外,它还具有独特的特性,还添加了对国际化支持、资源访问支持、以及事件传播等方面的支持。
  • 性能方面:后者是一次性加载并初始化所有的Bean对象,而前者是需要哪个才去加载哪个,因此更加轻量(空间换时间)

 4、方法注解(@Bean)

考虑以下场景:1、使用外部包里面的类,没办法添加类注解

2、一个类,需要多个对象,比如多个数据源 

1、一个对象的情况 

 示例:

package com.example.example1.bean;import lombok.Data;import javax.lang.model.element.NestingKind;
@Data
public class User {private String name;private int age;
}
package com.example.example1.bean;
import org.springframework.context.annotation.Bean;public class BeanConfig {@Beanpublic User user(){User user = new User();user.setName("zhangsan");user.setAge(12);return user;}
}

 

User user = context.getBean(User.class);System.out.println(user);

 让我查看运行结果,结果报错了

什么原因造成的呢?

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

对上述代码进行修改

package com.example.example1.bean;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;@Component
public class BeanConfig {@Beanpublic User user(){User user = new User();user.setName("zhangsan");user.setAge(12);return user;}
}

再次运行:

2、多个对象的情况 

 

从运行结果可以看出:@Bean注解的Bean,bean名称就是它的方法名

所以我们根据名称来获取bean对象 

 3、重命名Bean

    @Bean(name = {"u3","user3"})public User user3(){User user = new User();user.setName("wangwu");user.setAge(14);return user;}
 User u3 = (User) context.getBean("u3");System.out.println(u3);

 

5、扫描路径

问题:使用前面学过的四个注解声明Bean,一定会生效吗?

答案是不一定的,bean要想生效,还需要被Spring扫描 

  1. 通过@CompontentScan 

@ComponentScan({"com.example.example1"}) 

五、DI详解 

 依赖注入是一个过程,是指IoC在创建Bean时,去提供运行时所依赖的资源,而资源指的就是对象,之前,我们使用@Autowired这个注解,完成了依赖注入的操作

简单来说,就是把对象取出来放到某个类属性中

1、依赖注入的三种方法 

1)属性注入(Field Injection)Autowired

@Controller
public class UserController {@Autowiredprivate UserService userService;public void sayHi() {System.out.println("祝你好运,小李");userService.sayHi();}
}

 

@Service
public class UserService {public void sayHi() {System.out.println("祝你幸福快乐,小李");}
}
      UserController userController = (UserController) context.getBean("userController");userController.sayHi();

 

2) 构造方法注入(Constructor Injection)

 

package com.example.example1.controller;import com.example.example1.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;@Controller
public class UserController2 {private UserService userService;@Autowiredpublic UserController2 (UserService userService) {this.userService = userService;}public void sayHi() {System.out.println("祝你好运,小李");userService.sayHi();}
}

注意:如果类只有一个构造方法,那注解可以省略,反之则不行 

3)Setter注入(Setter Jniection)

2、三种注入的优缺点分析 

• 属性注⼊ ◦:

优点: 简洁,使⽤⽅便;

◦ 缺点: ▪ 只能⽤于 IoC 容器,如果是⾮ IoC 容器不可⽤,并且只有在使⽤的时候才会出现 NPE(空指 针异常) ▪ 不能注⼊⼀个Final修饰的属性

• 构造函数注⼊(Spring 4.X推荐)

◦ 优点: ▪ 可以注⼊final修饰的属性 ▪ 注⼊的对象不会被修改 ▪ 依赖对象在使⽤前⼀定会被完全初始化,因为依赖是在类的构造⽅法中执⾏的,⽽构造⽅法 是在类加载阶段就会执⾏的⽅法. ▪ 通⽤性好, 构造⽅法是JDK⽀持的, 所以更换任何框架,他都是适⽤的

◦ 缺点: ▪ 注⼊多个对象时, 代码会⽐较繁琐

• Setter注⼊(Spring 3.X推荐)

◦ 优点: ⽅便在类实例之后, 重新对该对象进⾏配置或者注⼊

◦ 缺点: ▪ 不能注⼊⼀个Final修饰的属性 ▪ 注⼊对象可能会被改变, 因为setter⽅法可能会被多次调⽤, 就有被修改的⻛险. 

3、@Autowired存在问题(当同一类型存在多个bean时)

@Autowird 与 @Resource的区别

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

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

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

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

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

相关文章

嵌入式Linux系统编程 — 5.7 Linux系统中proc文件系统

目录​​​​​​​ 1 proc文件系统简介 2 proc 文件系统的使用 2.1 使用 cat 命令读取 2.2 使用 read()函数读取 1 proc文件系统简介 /proc 文件系统&#xff0c;也称为进程信息文件系统&#xff08;Process Information file system&#xff09;&#xff0c;是一种在 Li…

Windows电脑自建我的世界MC服务器并与好友远程联机游戏教程

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

08:结构体

结构体 1、为什么需要结构体2、如何定义结构体3、怎么使用结构体变量3.1、赋值和初始化3.2、结构体变量的输出 1、为什么需要结构体 为了表示一些复杂的事物&#xff0c;而普通的基本类型无法满足实际要求。什么叫结构体 把一些基本类型数据组合在一起形成的一个新的数据类型&…

高性能全局内存池

什么时候使用高性能全局内存池&#xff1f; 1.高并发下有些资源需要被频繁创建和销毁&#xff0c;我们都知道系统调用是很消耗资源的。因此&#xff0c;内存池是一块申请好的资源放在缓存里。 2.频繁使用时增加了系统内存的碎片&#xff0c;降低内存使用效率。内存分配必须起…

11083 旅游背包(优先做)

这个问题可以使用动态规划来解决。我们可以定义一个三维数组dp&#xff0c;其中dp[i][j][k]表示前i种物品&#xff0c;总体积不超过j&#xff0c;总重量不超过k的最大价值。 我们可以使用四重循环来填充这个数组。外层循环遍历所有的物品&#xff0c;第二层循环遍历所有可能的…

2024软件设计师笔记之考点版(一考就过):考试前一天 考点记忆版

软件设计师之一考就过&#xff1a;成绩版 1、栈区&#xff1a;函数调用和返回&#xff0c;由系统控制&#xff1b;存非静态局部变量&#xff1b;用栈实现嵌套调用&#xff08;递归调用&#xff09;&#xff0c;逆波兰式业绩也叫后缀式&#xff0c;用栈进行求值 2、堆区&#x…

Big Data Tools插件

一些介绍 在Jetbrains的产品中&#xff0c;均可以安装插件&#xff0c;其中&#xff1a;Big Data Tools插件可以帮助我们方便的操作HDFS&#xff0c;比如 IntelliJ IDEA&#xff08;Java IDE&#xff09; PyCharm&#xff08;Python IDE&#xff09; DataGrip&#xff08;SQL …

【RabbitMQ问题踩坑】RabbitMQ设置手动ack后,消息队列有多条消息,只能消费一条,就不继续消费了,这是为什么 ?

现象&#xff1a;我发送5条消息到MQ队列中&#xff0c;同时&#xff0c;我在yml中设置的是需要在代码中手动确认&#xff0c;但是我把代码中的手动ack给关闭了&#xff0c;会出现什么情况&#xff1f; yml中配置&#xff0c;配置需要在代码中手动去确认消费者消费消息成功&…

教学技能大赛包括哪些内容

在教育的广阔天地里&#xff0c;教师的角色至关重要。他们不仅是知识的传递者&#xff0c;更是学生心灵成长的引导者。那么&#xff0c;当教师们聚集一堂&#xff0c;参加一场教学技能大赛时&#xff0c;会有哪些内容成为他们展示自我、互相学习的舞台呢&#xff1f; 教学技能大…

瓦罗兰特报错57/error code59/报错903的解决办法

《无畏契约》在注重产品设计之预&#xff0c;也注重世界观、英雄性格的塑造&#xff0c;里面的英雄灵感来源于不同的国家和地区&#xff0c;有非常本土化的特色&#xff0c;每个英雄的性格人设非常鲜明。这些人物特色让这款游戏有了新的玩法。很多玩家都进入到游戏体验。然后有…

SeeSR: Towards Semantics-Aware Real-World Image Super-Resolution

CVPR2024 香港理工大学&OPPO&bytedancehttps://github.com/cswry/SeeSR?tabreadme-ov-file#-licensehttps://arxiv.org/pdf/2311.16518#page5.80 问题引入 因为有些LR退化情况比较严重&#xff0c;所以超分之后的结果会出现语义的不一致的情况&#xff0c;所以本文训…

Python入门 2024/7/1

目录 第一个程序hello world 数据类型 注释 变量 用type类型查看数据类型 ​编辑 数据类型转换 ​编辑 标识符 运算符 字符串的三种定义方式 字符串拼接 ​编辑​编辑 字符串格式化 第一个程序hello world 区分c和python c是printf python是print print("h…

晶振在硬件系统中的位置选择与优化策略

在现代电子设备中&#xff0c;晶振扮演着至关重要的角色&#xff0c;它们提供稳定且精确的时钟信号&#xff0c;是系统心脏般的存在。然而&#xff0c;晶振的性能不仅取决于其本身的质量&#xff0c;还与它在硬件系统中的位置选择紧密相关。一个恰当的位置能够最大限度地减少外…

基于K线最短路径构造的非流动性因子

下载地址https://download.csdn.net/download/SuiZuoZhuLiu/89492221

nodejs--【Express基本使用】

10 【Express基本使用】 https://www.expressjs.com.cn/ 基于 Node.js 平台&#xff0c;快速、开放、极简的 web 开发框架。 1.Express的安装方式 Express的安装可直接使用npm包管理器上的项目&#xff0c;在安装npm之前可先安装淘宝镜像&#xff1a; npm install -g cnpm -…

领先Intel 旗舰60%,AMD锐龙9000系桌面CPU彻底杀疯了

早在月初台北国际电脑展上&#xff0c;Intel 公布了下一代低功耗移动端处理器 Lunar Lake。 也就是第二代移动版酷睿 Ultra。 而作为叫板王&#xff0c;AMD 丝毫不怂&#xff0c;不但掏出了 Ryzen AI 300 移动端处理器应对。 还抢在 Intel 之前带来了全新一代 Zen 5 架构 Ryz…

前端vue项目升级nodejs后无法运行了

问题描述&#xff1a; 运行、打包都正常的vue项目&#xff0c;在将nodejs升级到v20.14.0后&#xff0c;均报错了&#xff1a; Error: error:0308010C:digital envelope routines::unsupported opensslErrorStack: [ error:03000086:digital envelope routines::initializ…

制造业如何拥抱数字化?百数服务商的转型策略与实践

制造业作为实体经济的主体部分&#xff0c;也是核心部分&#xff0c;发挥着基础性、主导性和引领性作用。推动制造业数字化转型是实现经济高质量发展的必由之路。 在这场数字化浪潮中&#xff0c;低代码平台作为一种新兴的技术手段&#xff0c;逐渐受到了企业的青睐。其能够在…

Web基础与HTTP协议:

Web基础与HTTP协议 Web&#xff1a;就是我们所说的页面&#xff0c;打开网站所展示的页面。&#xff08;全球广域网&#xff0c;万维网&#xff09; 分布式图形信息系统。 http https &#xff08;加密的&#xff09;超文本传输协议 分布式&#xff1a;计算机系统或者应用程序…

vue3引入本地静态资源图片

一、单张图片引入 import imgXX from /assets/images/xx.png二、多张图片引入 说明&#xff1a;import.meta.url 是一个 ESM 的原生功能&#xff0c;会暴露当前模块的 URL。将它与原生的 URL 构造器 组合使用 注意&#xff1a;填写自己项目图片存放的路径 /** vite的特殊性…