SpringIOCDI—第一讲

文章目录

  • 什么是IOC
    • 什么是控制,谁控制谁
    • 什么是反转,从什么反转到什么了
  • IOC的注解
    • 五大类注解
      • @Controller注解(控制器存储)
      • @Service(服务存储)
      • @Repository(仓库存储)
      • @Componet(组件存储)
      • @Configuration(配置存储)
    • 为什么这么多注解?
    • 类注解之间的关系
    • Bean的命名规则
    • 什么是方法注解(@Bean)
      • Bean注解
      • Bean的重命名
  • 什么是DI
    • @Autowired注解的局限性
      • @Primary注解
      • @Primary注解
      • @Resource
    • DI注入的方式
      • 构造方法注入
      • Setter方式注入

什么是IOC

IOC中文叫做控制反转,这是一种设计思想,那么什么是控制反转呢?想明白这个概念我们就要搞明白这两个概念

什么是控制,谁控制谁

首先是第一个概念谁控制谁呢?首先我们先搞明白谁是被控制的一方,在这里被控制的一方就是我们的各种对象,那么在传统的javaSE的程序设计中,我们创建对象是通过new来进行创建的,而IOC是有一个专门的容器来进行这些对象的创建和管理。因此这里的控制指的就是对我们创建对象的控制。那么回到那个问题谁控制了谁?:答案很明显了,是IOC容器控制了对象,控制了什么呢?控制了外部资源的获取

什么是反转,从什么反转到什么了

那么什么是反转呢?在传统的应用程序中是由我们自己在对象中主动控制获取依赖对象而反转的含义的就是由容器帮助我们进行对象的创建和存取。那么Spring想要帮我们进行存取对象该怎么做呢?答案是通过注解的形式

IOC的注解

想要将对象存储在spring中有两种方式来实现
1、首先是可以通过类注解的形式
2、可以通过方法注解的形式

五大类注解

首先就是五大类注解,这几个类注解都有哪些呢?分别是如下注解

@Controller注解(控制器存储)

该注解的使用方式如下

package com.example.spring_ioc;import org.springframework.stereotype.Controller;@Controller
public class UserControl {public void doUserControl(){System.out.println("doUserControl ....");}
}

首先我们先写出一个被controller注解的类,然后我们来进行获取bean

package com.example.spring_ioc;import com.example.spring_ioc.Control.*;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.ComponentScan;
//然后在程序上下文中进行调用。
@SpringBootApplication
public class SpringIocApplication {public static void main(String[] args) {ApplicationContext context=SpringApplication.run(SpringIocApplication.class, args);UserControl userControl=context.getBean(UserControl.class);userControl.doUserControl();}}

那么上面就是我们通过@Controller注解进行修饰之后得到的程序,这里我们来进行运行一下来看看
在这里插入图片描述
这里我们发现我们的程序运行起来了。

@Service(服务存储)

在用法上大致相同我们来看一下代码

package com.example.spring_ioc;import org.springframework.stereotype.Service;@Service
public class UserService {public void doUser(){System.out.println("doUser ....");}
}

那么有了上面的用列我想大家也能推到出来其余的三个注解在使用上也是大差不差的。

@Repository(仓库存储)

package com.example.spring_ioc;import org.springframework.stereotype.Repository;@Repository
public class ResponceUser {public void doRespository(){System.out.println("doRepository ....");}
}

@Componet(组件存储)

package com.example.spring_ioc;import org.springframework.stereotype.Component;@Component
public class ComponetUser {public void doComponet(){System.out.println("doComponetuser .....");}
}

@Configuration(配置存储)

package com.example.spring_ioc;import org.springframework.context.annotation.Configuration;@Configuration
public class ConfigurationUser {public void doConfiguration(){System.out.println("@Configuration ...");}
}

为什么这么多注解?

相信看到这里很多人会对这里有个疑惑,既然用法和作用都差不多为什么还要有这么多注解?直接就弄一个不就可以了吗?其实这是因为这个东西就跟我们的车牌号是一个道理的,在我们车牌号中我们不同的城市我们的车牌号的前面两个字符是不一样的,那么为什么这样做呢?这样做除了说是节约号码之外还有一个好处就是我们可以通过车牌迅速的确定这个车辆是哪个地方的,比如说你看到了豫A那么你第一个想到的就是河南郑州。这是类似的,有了这些注解也可以帮助我们开发者人员迅速知道这块代码是哪一层的。作用是什么。那么说到这里就涉及到了我们的工程分层。分层图如下所示
在这里插入图片描述

类注解之间的关系

在这里插入图片描述
通过查看 @Controller / @Service / @Repository / @Configuration 等注解的源码发现:这些注解都有一个@Component注解。说明他们本身就属于@Component的子类。

Bean的命名规则

这里为什么要提到Bean的命名规则呢?因为我们在获取Bean对象的时候其实我们也是可以通过类的名称来进行获取的而名称获取就需要一定的规则来规范你所命名的名称了。
如下在这里插入图片描述
首先我们有图中的这些类,这些类的命名呢都是首字母大写那么我们根据这些类的名称去获取的时候我们应该怎么遵循什么规则去获取呢?那么代码如下

package com.example.spring_ioc;import com.example.spring_ioc.Control.*;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.ComponentScan;@SpringBootApplication
public class SpringIocApplication {public static void main(String[] args) {ApplicationContext context=SpringApplication.run(SpringIocApplication.class, args);ConfigurationUser configurationUser=(ConfigurationUser)context.getBean("configurationUser");configurationUser.doConfiguration();}
}

这里我们可以看到我们需要给首字母大写转换为小写,此外假如说你的类名称前两个首字母都是大写的话那就不需要转换了,转换后甚至有可能出粗呢。

什么是方法注解(@Bean)

讲完上面的五大注解之后我们来谈一下什么是bean,bean的作用是什么。我们上面说了五大注解是加在了类上的因此叫做类注解,而bean则是方法上的。那么他们直接有什么区别呢?这里先思考一个问题,在上面我们通过类注解去进行了获取对象等,那么这里我们获取到的对象是同一个对象吗?也就是假如说我们对同一个类获取了两次对象那么这两个对象是同一个吗?我们来看一下吧。

package com.example.spring_ioc;import com.example.spring_ioc.Control.*;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.ComponentScan;@SpringBootApplication
public class SpringIocApplication {public static void main(String[] args) {ApplicationContext context=SpringApplication.run(SpringIocApplication.class, args);ConfigurationUser configurationUser=(ConfigurationUser) context.getBean("configurationUser");ConfigurationUser configurationUser11=context.getBean(ConfigurationUser.class);System.out.println(configurationUser11==configurationUser);}}

那么我们来看一下这个代码的运行结果吧
在这里插入图片描述
很明显结果是为true也就是说这里创建出来的两个对象是同一个对象,可是我们在实际开发中有很多情况肯定是不希望这样的那么这时候就需要用到bean注解了。

Bean注解

首先我们先来看一下代码如何操作

package com.example.spring_ioc.Control;import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Controller;@Controller
public class TestControl {public void doCOntrol(){System.out.println("docontrol .....");}@Beanpublic TestControl control(){TestControl control=new TestControl();return control;}@Beanpublic TestControl control1(){TestControl control1=new TestControl();return control1;}
}

然后我们来看一下如何获取到对象

package com.example.spring_ioc;import com.example.spring_ioc.Control.*;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.ComponentScan;@SpringBootApplication
public class SpringIocApplication {public static void main(String[] args) {ApplicationContext context=SpringApplication.run(SpringIocApplication.class, args);TestControl control=context.getBean(TestControl.class);control.doCOntrol();}}

在这里插入图片描述
这里我们可以发现我们想要继续通过之前的方法去获取对象是不行的了,那么他报错的原因也很简单那就是他不知道该获取哪个对象,就像一个班级里面有很多个男生,你直接就喊出来一个男生,这时候肯定会懵一下感到疑惑你找谁啊?所以代码也是这样的那么该怎么办呢?答案就是通过名称获取

package com.example.spring_ioc;import com.example.spring_ioc.Control.*;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.ComponentScan;@SpringBootApplication
public class SpringIocApplication {public static void main(String[] args) {ApplicationContext context=SpringApplication.run(SpringIocApplication.class, args);TestControl control=(TestControl) context.getBean("control");TestControl control1=(TestControl)context.getBean("control1");System.out.println(control1==control);control.doCOntrol();control1.doCOntrol();}}

那么我们来看一下运行的结果如何
在这里插入图片描述
我们发现这里的运行结果表明我们创建出来的两个对象是不同的两个对象

Bean的重命名

使用Bean注解是可以对类进行重命名的,那么如何进行重命名呢?我们来看一下代码

package com.example.spring_ioc.Control;import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Controller;@Controller
public class TestBean {@Bean("u1")public TestBean testBean1(){TestBean testBean=new TestBean();return testBean;}public void run(){System.out.println("runTestBean");}
}

那么这时候我们想要获取对象就可以通过重命名之后的名字进行获取了

什么是DI

那么接下来什么是DI呢?DI也叫做属性注入,什么是属性注入?我们来看一下下面的这个代码
TestDI

package com.example.spring_ioc.Control;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Controller;
import org.springframework.stereotype.Service;@Configuration
public class TestDI {@AutowiredPerson person;@Beanpublic TestDI t(){TestDI testDI=new TestDI();return testDI;}public void run(){System.out.println("+++");}}

Person

package com.example.spring_ioc.Control;import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Controller;@ToString
@Controller
public class Person {public String name="zyfcl";public Integer age=20;@Beanpublic Person p(){Person person=new Person();return person;}
}

从上面两个代码也许就能看出来,首先Person是我们的一个Controller类,也就是已经注入了spring容器中了并且使用Bean将p方法进行注解,此时就相当于告诉了spring我们这个类的对象调用的是我们的这个方法进行获取,然后在TestDI类中我们使用了person类创建的person对象,并且这个对象使用了Autowired注解,也就是会进行注入。

@Autowired注解的局限性

首先我们要明白@Autowired注解的匹配原则首先他是先按照类型进行匹配的但是这样势必会有下面的这个问题那就是假如说类型匹配上了但是我们使用了@Bean注解注解了多个方法去进行创造这个对象,那么到底该返回哪一个呢?如下代码


package com.example.spring_ioc.Control;import lombok.ToString;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@ToString
@Configuration
public class Person {public String name;public Integer age;@BeanPerson person1(){Person person2=new Person();person2.age=21;person2.name="cl";return person2;}@Beanpublic Person person2(){Person person1=new Person();person1.name="zyf";person1.age=19;return person1;}
}package com.example.spring_ioc.Control;import lombok.ToString;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@ToString
@Configuration
public class Person {public String name;public Integer age;@BeanPerson person1(){Person person2=new Person();person2.age=21;person2.name="cl";return person2;}@Beanpublic Person person2(){Person person1=new Person();person1.name="zyf";person1.age=19;return person1;}
}
package com.example.spring_ioc.Control;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
public class TestDI {@AutowiredUserInfo userInfo;@AutowiredPerson person;@Beanpublic TestDI t(){TestDI testDI=new TestDI();return testDI;}public void run(){System.out.println("+++");System.out.println(person);}public void  run2(){System.out.println(userInfo);}}

那么结合上面的两段代码我们来想一想,这里会不会报错呢?这个person该实例化为哪个呢?其实这里spring也不知道,那么最终怎么办呢?有些情况下可能会报错,有些情况下可能会给你初始为空。我这边是初始为空的。
那么上面的情况怎么解决呢?那就是下面三个注解
首先第一个

@Primary注解

这个注解可以理解为默认的意思也就是出现了上面的情况的话那么就会默认为被这个注解修饰的那种方法。
在这里插入图片描述

@Primary注解

第二种就是这样的注解,表示你想要将其使用哪个对象,在这里面写入你希望的方法名称即可
在这里插入图片描述

@Resource

第三种就是Resource注解它的用法和primary是差不多的都是自己指定。
在这里插入图片描述

DI注入的方式

上面只讲了属性注入实际上我们还有别的方式进行注入

构造方法注入

在这里插入图片描述

这里就是构造的方式注入

Setter方式注入

这里也就相当于写了一个set方法进行了注入。

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

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

相关文章

React从next/navigation和next/router导入useRouter区别

在Next.js项目中,从next/navigation和next/router导入useRouter有以下几点不同,它们分别适用于不同的Next.js版本,并提供不同的功能: next/router 版本兼容性:next/router适用于Next.js v13之前的版本。功能&#xf…

什么是vue

Vue.js(通常简称为 Vue)是一个用于构建用户界面的渐进式 JavaScript 框架。它由尤雨溪(Evan You)创建,并于2014年首次发布。Vue 设计的目的是能够灵活地适应开发者的需求,可以通过引入不同的插件和库来构建…

云端漫步:搭建个人博客的移动云之旅

💂作者简介: Thunder Wang,阿里云社区专家博主,华为云云享专家,腾讯云社区认证作者,CSDN SAP应用技术领域优质创作者。在学习工作中,我通常使用偏后端的开发语言ABAP,SQL进行任务的完…

每日一题(3)——统计合格率(不会哦)

我们来看一个案例: 如何理解 pass【j】 ? 为什么pass[0]3,pass[1]4? 我一直没有想通,自己重新测试了一些数据,还是没有想明白,希望大家能够集思广益,点拨点拨: 下面的数组我随便使用的数据, …

基于EBAZ4205矿板的图像处理:09基于sobel边缘检测的图像锐化

基于EBAZ4205矿板的图像处理:09基于sobel边缘检测的图像锐化 项目全部文件 随后会上传项目全部文件 先看效果 锐化的有点过头了,不过我也懒得改了,想要改也很简单,无非就是给卷积运算后的结果加个系数,通过改系数调…

springmvc不同格式的参数解析

参数解析 application/x-www-form-urlencoded格式 这种格式就是传统的表单提交格式,就是一个个的键值对,会进行url编码,使用springmvc接收时使用RequestParam来进行接收,与传入的字段一一对应,此时使用的参数处理器是R…

【数据分析】Numpy和Pandas库基本用法及实例--基于Japyter notebook实现

各位大佬好 ,这里是阿川的博客 , 祝您变得更强 个人主页:在线OJ的阿川 大佬的支持和鼓励,将是我成长路上最大的动力 阿川水平有限,如有错误,欢迎大佬指正 承接上篇的博客 数据分析—技术栈和开发环境搭…

家政预约小程序03分类管理

目录 1 创建数据源2 搭建导航菜单3 搭建小程序4 设置变量5 变量绑定总结 家政预约小程序里,在首页需要展示家政可以开展的各类业务。我们把业务按照类别进行划分,本篇我们介绍一下管理后台的维护功能以及小程序的展示功能。 1 创建数据源 为了管理和展示…

2024年二建准考证打印入口已开通!

24年二建将于6月1日、2日举行,目前西藏、陕西准考证打印入口已开通,各省也将陆续开始准考证打印工作。 2024二建考试时间安排 2024二建准考证打印时间 二建准考证打印须知 01 准考证打印信息显示空白怎么办? 1)使用电脑自带的浏览器重新试一下。 2)…

27.Java中单例模式的实现方式

一、单例模式 单例模式(Singleton Pattern)是一种创建型设计模式,它确保一个类只有一个实例,并提供一个全局访问点来访问这个唯一实例。 单例模式中: 这个类只能有一个实例这个类必须自己创建自己的唯一实例这个类必须…

Qt 报错总结 No suitable kits found

目录 “No suitable kits found” 解决 解决方法参考: chatGPT辅助解决QT构建报错error: multiple target patterns 我的解决方法:把语言设置为空 “No suitable kits found” 解决 没有找到合适的kits套件,在安装Qt Creator时没有安装Min…

高阶路由过渡处理方案 —— 浏览器堆栈主动介入

目录 01: 前言 02: VueRouter 过渡动效可行性分析 03: 主动介入浏览器堆栈管理,分析可行性方案 04: 主动介入浏览器堆栈管理 05: 基于 GSAP 实现高阶路由过渡动画分析 06: 基于 GSAP 实现高阶路由过渡动画处理 07: 通用组件:navbar 构建方案分析…

Kafka之【消费消息】

Kafka之【消费消息】

Redis基础篇

文章目录 2 Redis入门概述3 Redis10大数据类型3.1 Redis自字符串String3.2 Redis列表List3.3 Redis哈希Hash3.4 Redis集合Set3.5 Redis有序集合Sorted Set3.6 Redis地理空间 GEO3.7 Redis基数统计 HyperLogLog3.8 Redis位图bitmap3.9 Redis位域bitField3.10 Redis流Stream 4 Re…

Elasticsearch 分析器的高级用法一(同义词,高亮搜索)

Elasticsearch 分析器的高级用法一(同义词,高亮搜索) 同义词简介分析使用同义词案例 高亮搜索高亮搜索策略unifiedplainvh 同义词 简介 在搜索场景中,同义词用来处理不同的查询词,有可能是想表达相同的搜索目标。 例…

基于Go实现的分布式主键系统

基于Go实现的分布式主键系统 摘要 随着互联网的发展,微服务得到了快速的发展,在微服务架构下,分布式主键开始变得越来越重要。目前分布式主键的实现方式颇多,有基于数据库自增的、基于UUID的、基于Redis自增的、基于数据库号段的…

探寻最强性能云电脑:ToDesk云电脑、无影云、网易云游戏、易腾云横测大比拼

大家好,我是herosunly。985院校硕士毕业,现担任算法研究员一职,热衷于机器学习算法研究与应用。曾获得阿里云天池比赛第一名,CCF比赛第二名,科大讯飞比赛第三名。拥有多项发明专利。对机器学习和深度学习拥有自己独到的…

恶劣天候鲁棒三维目标检测论文整理

恶劣天候鲁棒三维目标检测论文整理 Sunshine to Rainstorm: Cross-Weather Knowledge Distillation for Robust 3D Object DetectionRobo3D: Towards Robust and Reliable 3D Perception against CorruptionsLossDistillNet: 3D Object Detection in Point Cloud Under Harsh W…

虚拟设备和物理平台之间的资源分配

虚拟设备和物理平台之间的资源分配 在物理硬件设备平台上通过虚拟机(VM)或其他虚拟化技术运行多个虚拟化设备时,这些虚拟化设备会消耗物理硬件资源。 虚拟化设备如何消耗资源? CPU 资源 虚拟机会消耗物理 CPU 的计算能力。每个虚…

基于自抗扰控制器和线性误差反馈控制律(ADRC-LSEF)的控制系统simulink建模与仿真

目录 1.课题概述 2.系统仿真结果 3.核心程序与模型 4.系统原理简介 4.1 ADRC原理 4.2 线性误差反馈控制律(LSEF) 4.3 ADRC-LSEF融合系统 5.完整工程文件 1.课题概述 基于自抗扰控制器和线性误差反馈控制律(ADRC-LSEF)的控制系统simulink建模与仿真。 2.系统仿真结果 …