Spring IoC DI

news/2025/1/14 22:44:03/

 Spring IoC & DI

        前置知识: 什么是容器?

        容器: 装东西的装置.Spring就是包含了众多工具方法的IoC容器

 1.1 Spring IoC & DI 概念

        我们先来看这么一个例子:

        我们现在的需求是造车:

        先设计轮子,根据轮子大小设计底盘,根据底盘设计车身,根据车身设计整个车.

我们给一个指定的大小就能生成车.

        

        但是此时有个问题,我增加需求: 我需要修改车轮的颜色,此时就要一路沿着车轮,底盘,车身一路改过去.耦合性就很大

        我们换一种思路,先设计车大致样子,再根据车的样子设计车声,根据车身来设计底盘,最后根据底盘设计轮子.

        

        直接把依赖对象注⼊将当前对象中,依赖对象的控制权不再由当前类控制了.

对比一下俩种方式:

此时我们修改需求,就直接在main里面修改即可,这就完成了代码的解耦

此时main就是一个,第三方的资源管理.这个main方法就对应着我们的Spring容器,我们的Spring,就已经创建了这些对象,我们直接拿来用就好了

        

        IoC (Inversion of Control) 控制反转,也就是控制权反转,指的是对对象的控制权反转.之前我们就使用过IoC: @RestController,表示申明这个对象,把这个对象交给Spring进行管理.也就是把创建对象的控制权交给Spring来进行管理 

        DI (Dependency Injection) 依赖注入,在运行时间为程序提供运行时所依赖的资源.

总的来说就是: 在程序运行的时候,动态的把依赖进行赋值,然后注入到这个对象里面去.

        看个例子:

        这里面的BookService对象是由BookController来进行创建的,但是此时我不想自己创建,我想直接交给Spring来进行创建.

        我们通过@Component注解,把BookService这个对象交给Spring来进行创建

        然后我们使用DI,从Spring里面把这个对象取出来.此时我们需要使用@Autowired注解,把BookService这个对象从Spring里面取出来.

       

对比: 此时我们发现我们并没有new一个对象,而是直接使用存在Spring里面的对象

  1.2 IoC的好处(面试八股文)

    资源不用使用资源的双方管理,而是由不使用资源的第三方进行管理,这样就有下面几个好处,第一: 资源集中管理,实现资源的可配置和易管理: IoC容器会帮我们管理一些资源(对象),为你需要使用时,只需要从IoC容器中取就行. 第二: 降低了资源双方的依赖程度,也就是耦合度,简单来讲就是降低了耦合度

  1.3 IoC和DI之间的关系

        IoC是控制反转,也就是有个第三方的容器(比如Spring)帮我创建好了对象.DI就是从这个容器里面拿到这个对象,然后进行赋值.

   1.4 什么样的对象适合交给Spring进行管理?

        无状态的对象,也就是不管谁来访问,结果都是一样的.

 3.1 bean的介绍

        什么是bean?

        简而言之: bean就是归spring管理的对象

        IoC&DI和bean的关系

        Ioc 控制反转: 把创建对象的控制权交给了Spring进行管理,使用@Controller,@Component...这个就是bean的存储

        DI 依赖注入: 从Spring里面把创建的对象拿出来并且进行赋值,使用@Autowired 这个就是bean的获取

        前置知识:

        ApplicationContext :里面装的是Spring运行环境所有的信息

        ApplicationContext 和BeanFeactory关系以及区别(八股文)

        1. 关系: 他俩是父子关系ApplicationContext是父,BeanFeactory是子,BeanFeactory的功能,ApplicationContext都有,除此之外ApplicationContext还具备 资源 环境管理等功能.

        2. 区别: Beanfactory是懒加载(用到的时候才会创建这个Bean),ApplicationContext是提前加载.ApplicationConetxt性能会比较好,但是因为是提前把所有的Bean都加载出来了,那么就会浪费空间.但是现在基本上内存不值钱了,因此大多还是用ApplicationContext.

  3.1.2 bean的存储

        IoC告诉Spring,我要存储那个bean,如何告诉?俩种方式:1.类注解,2.方法注解

        类注解

        类注解有5种,分别是@Controller(表现层)@Componet(组件相关)@Service(业务逻辑层)@Configuration(配置相关)@Repository(数据层)

        1. @Controller

        直接在类上面加入@Controller注解,把这个对象放到Spring里面

        

        然后我们取出来

        这时需要启动类,这个是个导包问题

        此时我们获得bean有很多方式,我们只介绍三种

        1.通过bean的名称获得bean

        我们先认识一下什么是bean的名称

        类型相当于学生的名称(可能有重复的,一个类型可能往Spring里面放置了多个对象),Bean的名称是在Spring容器种唯一的,类似于学生的学号或者身份证号.总而言之,bean的名称是唯一的.

        我们运行一下启动类,成功把放进去的Spring对象取出来了

        2.通过bean的类型获得bean

        这里报错的原因就是,我们根据类型获取bean,此时里面应该是小驼峰

        改成小驼峰之后成功了

        但是有一种特殊情况,也就是开头俩个字母是连着大写的类.当我们的类名字超过连续俩个字母是大写的,那么我类的名称就是我们类原始的名称,而不是小驼峰的形式

        修改后,运行成功

              此时我们需要了解一下bean的命名规则

        bean的命名规则

我们看下官⽅⽂档的说明: Bean Overview :: Spring Framework

总结:

默认情况下:首字母小写的驼峰表示.

特殊情况:如果类名称前俩位都是大写,和类名的名称是一样的

       3. 通过类型和bean的名称一起获得bean    

       注意: 不管什么怎么取,都是同一个对象

        2. @Component

                我们使用@Component把这个对象放到Spring里面去

        此时我们只使用一种方式来拿出来        

        3. @Service

        我们在类上面加上@Service这个注解,把这个对象放在Spring里面

        取出来

        4. @Repository

        我们在这个类上面加上@Respository这个注解,把这个对象放到Spring里面去

        取出来

        5. @Configuration

        我们把@Configuration放到类的上面,把这个对象放到Spring里面

        取出来

五大类注解之间的关系:

基本上可以混用,但是不推荐.硬要混用,记住只要有路由映射就都使用Controller.其他条件都是能混用

方法注解

       1. 使⽤外部包⾥的类, 没办法添加类注解
       2. ⼀个类, 需要多个对象, ⽐如多个数据源这种场景, 我们就需要使⽤⽅法注解@Bean

   

        @Bean也是需要配合五大注解来使用的

注意:这个记得删除,spring3升级导致的lombok没生效(每次删完记得刷新一下)

        使用@Bean注解,把这个方法交给Spring进行管理(此时我们通过类名来获取)

        

        但是此时我们把多个同类型的Bean放进去,因为时单例模式,只能有一个

此时我们通过方法名称来获取

        @Bean的命名方式

        直接根据方法名称来命名(不管大小写)

       bean名称总结:


        1.五大注解
        类名: 首字母小写
        如果类名称,前俩位为大写,bean的名称为类名本身
        2.@Bean
        bean名称: 方法名 

        如何告诉Spring去扫描哪些程序?

        这个就和启动类有关系了.我们看一个例子

        我们修改启动类的目录结构

        再次运行,发现报错,这说明我们找不到我们的路径,启动类默认扫描路径是,他本层及下面的子目录.因为 启动类的源码包含了扫描路径的功能.

        我们可以通过@ComponentScan手动设定扫描路径.此时就可以了,这里注意,我们{}里面是可以放置多个位置的,比如:

@ComponentScan(basePackages = {"org.xiaobai","com.fasterxml.jackson.core.async"})

        

  3.1.3 bean的取出(DI注入的三种方式)

        DI我们使用的是@Autowired这个注解

          1 属性注入

        我们直接把@Autowired放在我们要使用的没有new的类的前面

        

          2 构造方法注入

        单个构造方法的情况

        

        多个构造方法的情况,发现报错了.因为Spring在创建对象的时候就是用的构造函数,此时我们有俩个构造函数,因此它只用无参的,那么我们创建出来的就是个null.默认我们用的是无参的.因此userService就是个空的对象.

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

        

        构造函数注入总结:

        1. 如果只有一个构造函数,不需要加入AutoWired

        2. 如果有多个构造函数,需要指定默认的构造函数(Autowired指定,如果没有指定就默认使用无参的构造函数)

        构造函数规范:

        如果添加构造函数,那就把无参的构造函数显示添加.添加构造函数的时候使用@AutoWired注解

          3 setter方法注入

              如果不加@Autowired,报错了,任然是空指针异常

  3.1.4 三种注入的优缺点(面试八股文)

        1. 属性注入

        优点: 简介,使用方便       

        缺点: 只能用于IoC容器,非IoC容器不可以使用

                不能注入一个final修饰的属性(也可以这么理解,后面setter方法一定会操控这个对象,对它进行赋值操作,那么final就不适合了)只有在使用的时候才会显示空指针异常.(idea不会给你爆红,运行之后才会有错误信息)

        2. 构造函数注入(Spring4.x版本)

        优点: 可以注入final修饰的属性

           注入的对象不会被修改                  

         依赖对象在使⽤前⼀定会被完全初始化,因为依赖是在类的构造⽅法中执⾏的,⽽构造⽅法是在类加载阶段就会执⾏的⽅法.

        通⽤性好, 构造⽅法是JDK⽀持的, 所以更换任何框架,他都是适⽤的(去除@Autowired也可以)

        3. Setter注入(Spring3.x推荐)

        优点: ⽅便在类实例之后, 重新对该对象进⾏配置或者注⼊
        缺点:不能注⼊⼀个Final修饰的属性
                注⼊对象可能会被改变, 因为setter⽅法可能会被多次调⽤, 就有被修改的⻛险.

        上面是解释版本,下面是纯记版本

  3.1.5 @Autowired存在问题

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

        先来看看正确运行

        

        我们使用属性注入,发现名称匹配不上就会根据类型来匹配,然后发现有三个这个类型的,不符合单例模式.

        三种解决方式:
        1. @Primary

         通过@Primary,把其中一个Bean设置成一个默认的bean(注意下面的代码我在UserInfo属性上少加了@Autowired注解

        2. @Qualifier

        通过@Qualifier,指定哪个是默认的Bean

        3. @Resource

        通过@Resource注解,指定Bean

        

        bean的重命名:

        常⻅⾯试题(面试八股文):

 他们都能实现对象的注入
@Autowird 与 @Resource的区别
1. @Autowired 是spring框架提供的注解,⽽@Resource是JDK提供的注解
2. @Autowired 默认是按照类型注⼊,⽽@Resource是按照名称注⼊. 相比于 @Autowired 来说,@Resource ⽀持更多的参数设置,例如 name 设置,根据名称获取 Bean。

@Autowired,@Qualified的执行流程(自己演示一下)

Spring, Spring Boot 和Spring MVC的关系以及区别(八股文)

         Spring 相当于火车,Spring MVC类似于售卖火车票(卖票肯定是基于火车这个条件的),一开始我们卖票就是在火车站线下买票.

        Spring Boot类似于12306,它不仅具备线上卖票(比线下更高效)的功能,还封装了买保险,订酒店,订外卖...功能模块.

        总而言之,一个项目有很多模块,Spring MVC是其中的一个模块,Spring Boot把包括Spring MVC的很多模块都封装起来了.简而言之: Spring Boot 是封装了更多功能,这个功能包含了Spring MVC的功能.也就是Spring Boot更加的高级.

        Spring:高铁

        Spring MVC(买票,坐车)

        Spring Boot(类似于12306)通过pom文件集成了很多东西进来

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

        之前的

        他们之间的关系图:

        Spring Core-> DI,IoC.这个是Spring的核心,Spring最原始的功能.对应的是Spring Framwork

        Spring MVC,Spring Data JPA,Spring Security都是基于Spring Core来进行开发的

        Spring Boot就是把上面的项目集成起来

        上面整个就称作Spring家族

补充: Spring发展历史

微服务: 是一种架构风格,旨在将一个大型的单体应用拆分成多个独立的小服务,每个服务都可以独立运行和部署.

Spring MVC 的实现方式现在采用Spring Boot 早期是使用Spring Core加上很多配置来实现的.

比如在美团买火车票,要登录12306的账号,它是基于12306的二次开发.

pom文件的一些解释(一般版本号我们加入其他地方的依赖的时候,选择不加,不然容易引起版本冲突)

补充: idea快捷键:把鼠标放在类上按Shift+Fn+F6(快速改名)

Ctrl+alt+L java代码的格式化


http://www.ppmy.cn/news/1563150.html

相关文章

React Error Boundary 错误边界限制

1. 基本概念 1.1 什么是 Error Boundary Error Boundary 是 React 16 引入的一个特性,它可以捕获子组件树中的 JavaScript 错误,记录错误并展示备用 UI,而不是让整个应用崩溃。大白话:嵌套组件某个组件出错时显示备用页面而非报…

使用Selenium进行网页自动化测试

在使用Selenium进行网页自动化测试时,获取网络请求数据(即network数据)并不直接由Selenium库提供。Selenium主要用于与网页内容进行交互(如点击、输入文本、获取页面元素等),但它本身不拦截或记录网络请求。…

贪心算法笔记

贪心算法笔记 大概内容 贪心就是对于一个问题有很多个步骤,我们在每一个步骤中都选取最优的那一个,最后得出答案。就是在一些函数中可行,但是有些比如二次函数,因为它的转折点不一定最优,就是不可行的。那么如何判断贪心呢?有这么几种 看时间复杂度,一般的就是 O ( n…

从前端视角看设计模式之创建型模式篇

设计模式简介 "设计模式"源于GOF(四人帮)合著出版的《设计模式:可复用的面向对象软件元素》,该书第一次完整科普了软件开发中设计模式的概念,他们提出的设计模式主要是基于以下的面向对象设计原则&#xff…

一学就废|Python基础碎片,OS模块

Python 中的操作系统模块提供了与操作系统交互的功能。操作系统属于 Python 的标准实用程序模块。该模块提供了一种使用依赖于操作系统的功能的可移植方式。os和os. path模块包括许多与文件系统交互的函数。 Python-OS 模块函数 我们将讨论 Python os 模块的一些重要功能&…

正点原子STM32F103战舰版电容触摸键学习

一、tpad.h代码 #ifndef __TPAD_H #define __TPAD_H#include "./SYSTEM/sys/sys.h"/******************************************************************************************/ /* TPAD 引脚 及 定时器 定义 *//* 我们使用定时器的输入捕获功能, 对TPAD进行检…

20250110_ PyTorch中的张量操作

文章目录 前言1、torch.cat 函数2、索引、维度扩展和张量的广播3、切片操作3.1、 encoded_first_node3.2、probs 4、长难代码分析4.1、selected4.1.1、multinomial(1)工作原理: 总结 前言 1、torch.cat 函数 torch.cat 函数将两个张量拼接起来,具体地是…

第27章 汇编语言--- 设备驱动开发基础

汇编语言是低级编程语言的一种,它与特定的计算机架构紧密相关。在设备驱动开发中,汇编语言有时用于编写性能关键的部分或直接操作硬件,因为它是接近机器语言的代码,可以提供对硬件寄存器和指令集的直接访问。 要展开源代码详细叙…