Java Spring IoCDI :探索Java Spring中控制反转和依赖注入的威力,增强灵活性和可维护性

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

💓 博客主页:从零开始的-CodeNinja之路

⏩ 收录文章:Java Spring IoC&DI :探索Java Spring中控制反转和依赖注入的威力,增强灵活性和可维护性

🎉欢迎大家点赞👍评论📝收藏⭐文章

目录

  • 前提小知识:高内聚低耦合
  • 一. IOC
    • 1.1 什么是IOC?
    • 1.2 IOC的实现
    • 1.3 IOC容器的优点
    • 1.4 IOC的存储
        • @Controller(控制器存储)
        • @Service(服务存储)
        • @Repository(仓库存储)
        • @Component(组件存储)
        • @Configuration(配置存储)
        • @Bean (方法注解)
    • 1.5 IOC注解总结概括
  • 二. DI
    • 2.1 什么是DI?
    • 2.2 DI的方法使用
        • 属性注入
        • 构造方法注入
        • Setter注入
        • 三种注入优缺点分析
    • 2.3 @Autowired存在的问题
        • @Primary
        • @Qualifier
        • @Resource
    • 2.4 @Autowird的注入流程图
  • 三. 总结

前提小知识:高内聚低耦合

我们一下要学习的内容都是为了实现⾼内聚低耦合来进行的
软件设计原则:⾼内聚低耦合.
⾼内聚指的是:⼀个模块中各个元素之间的联系的紧密程度,如果各个元素(语句、程序段)之间的联
系程度越⾼,则内聚性越⾼,即"⾼内聚"。
低耦合指的是:软件中各个层、模块之间的依赖关联程序越低越好。修改⼀处代码,其他模块的代码
改动越少越好.
在这里插入图片描述
⾼内聚低耦合⽭盾吗?
不⽭盾,⾼内聚指的是⼀个模块中各个元素之间的联系的紧密程度,低耦合指的是各个模块之间的紧
密程度
这就好⽐⼀个企业,包含很多部⻔,各个部⻔之间的关联关系要尽可能的⼩,⼀个部⻔发⽣问题,要尽
可能对降低对其他部⻔的影响,就是耦合.但是部⻔内部员⼯关系要尽量紧密,遇到问题⼀起解决,克
服.这叫做内聚.
⽐如邻⾥邻居,楼上漏⽔,楼下遭殃,就是耦合.家庭⼀个成员⽣病,其他成员帮忙照顾,就叫内聚.
⼀个家庭内部的关系越紧密越好,⼀个家庭尽可能少的影响另⼀个家庭,就是低耦合.
简单来说:就是在未来的工作中写出的代码尽量集中在一个路径中,但是每个程序与其它程序的关联度很低,以至于一个文件出错了并不影响其它程序的正常运行.

一. IOC

1.1 什么是IOC?

IoC是Spring的核⼼思想,也是常⻅的⾯试题,那什么是IoC呢?
IoC:InversionofControl(控制反转),也就是说Spring是⼀个"控制反转"的容器.
什么是控制反转呢?也就是控制权反转.什么的控制权发⽣了反转?获得依赖对象的过程被反转了
也就是说,当需要某个对象时,传统开发模式中需要⾃⼰通过new创建对象,现在不需要再进⾏创
建,把创建对象的任务交给容器,程序中只需要依赖注⼊(DependencyInjection,DI)就可以了.
我们⽤⼀句更具体的话来概括Spring,那就是:Spring是包含了众多⼯具⽅法的IoC容器
简单点来说:就是通过IOC的内置注解将被注解的内容放到Spring的大池子里,方便后续的调用(这样子应该很好理解)

1.2 IOC的实现

举个栗子:比如传统的造车过程是一级级的调用,如下:
在这里插入图片描述
以上程序的问题是:当最底层代码改动之后,整个调⽤链上的所有代码都需要修改.程序的耦合度⾮常⾼(修改⼀处代码,影响其他处的代码修改)

经过IOC实现后的流程图如下:
在这里插入图片描述
而IOC的目标就是为了降低耦合度,对于上面的例子来说就是将汽车每个部件的生产都交给第三方来处理,不让他们之间有联系,也就降低了耦合度
我们发现了⼀个规律,通⽤程序的实现代码,类的创建顺序是反的,传统代码是Car控制并创建了
Framework,Framework创建并创建了Bottom,依次往下,⽽改进之后的控制权发⽣的反转,不再
是使⽤⽅对象创建并控制依赖对象了,⽽是把依赖对象注⼊将当前对象中,依赖对象的控制权不再由
当前类控制了.
这样的话,即使依赖类发⽣任何改变,当前类都是不受影响的,这就是典型的控制反转,也就是IoC的
实现思想。

1.3 IOC容器的优点

资源不由使⽤资源的双⽅管理,⽽由不使⽤资源的第三⽅管理,这可以带来很多好处。第⼀,资源集
中管理,实现资源的可配置和易管理。第⼆,降低了使⽤资源双⽅的依赖程度,也就是我们说的耦合
度。

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

1.4 IOC的存储

在之前的⼊⻔案例中,要把某个对象交给IOC容器管理,需要在类上添加⼀个注解: @Component
⽽Spring框架为了更好的服务web应⽤程序,提供了更丰富的注解.
共有两类注解类型可以实现:

  1. 类注解:@Controller、@Service、@Repository、@Component、@Configuration.
  2. ⽅法注解:@Bean.
    接下来我们分别来看
@Controller(控制器存储)

使⽤@Controller存储bean的代码如下所⽰:

	@Controller // 将对象存储到 Spring 中
	public class UserController {
		public void sayHi(){
			System.out.println("hi,UserController...");
		}
	}
@Service(服务存储)

使⽤@Service存储bean的代码如下所⽰:

	@Service// 将对象存储到 Spring 中
	public class UserService {
		public void sayHi(String name) {
			System.out.println("Hi," + name);
		}
	}
@Repository(仓库存储)

使⽤ @Repository 存储bean的代码如下所⽰:

	@Repository
	public class UserRepository {
		public void sayHi() {
			System.out.println("Hi, UserRepository~");
		}
	}
@Component(组件存储)

使⽤@Component存储bean的代码如下所⽰:

	@Component
	public class UserComponent {
		public void sayHi() {
			System.out.println("Hi, UserComponent~");
		}
	}
@Configuration(配置存储)

使⽤@Configuration存储bean的代码如下所⽰:

	@Configuration
	public class UserConfiguration {
		public void sayHi() {
			System.out.println("Hi,UserConfiguration~");
		}
	}
@Bean (方法注解)

类注解是添加到某个类上的同时⽅法注解要配合类注解使⽤,但是存在两个问题:

  1. 使⽤外部包⾥的类,没办法添加类注解
  2. ⼀个类,需要多个对象,⽐如多个数据源
    这种场景,我们就需要使⽤⽅法注解 @Bean
    我们先来看看⽅法注解如何使⽤:
    ⽅法注解要配合类注解使⽤
@Component
public class BeanConfig {
	@Bean
	public User user(){
		User user = new User();
		user.setName("zhangsan");
		user.setAge(18);
		return user;
	}
}

1.5 IOC注解总结概括

  • @Controller:控制层,接收请求,对请求进⾏处理,并进⾏响应.

  • @Servie:业务逻辑层,处理具体的业务逻辑.

  • @Repository:数据访问层,也称为持久层.负责数据访问操作

  • @Configuration:配置层.处理项⽬中的⼀些配置信息.

  • @Component:其它4大类注解的父类

  • @Bean:方法注解,将一个方法交给Spring管理,同时要与类注解一起搭配使用

其实这些注解⾥⾯都有⼀个注解 @Component ,说明它们本⾝就是属于 @Component 的"⼦类".@Component 是⼀个元注解,也就是说可以注解其他类注解,如 @Controller , @Service ,
@Repository 等.这些注解被称为 @Component 的衍⽣注解.
@Controller , @Service 和 @Repository ⽤于更具体的⽤例(分别在控制层,业务逻辑层,持
久化层),在开发过程中,如果你要在业务逻辑层使⽤ @Component 或@Service,显然@Service是更
好的选择

二. DI

2.1 什么是DI?

DI:DependencyInjection(依赖注⼊)
容器在运⾏期间,动态的为应⽤程序提供运⾏时所依赖的资源,称之为依赖注⼊。
程序运⾏时需要某个资源,此时容器就为其提供这个资源.
从这点来看,依赖注⼊(DI)和控制反转(IoC)是从不同的⻆度的描述的同⼀件事情,就是指通过
引⼊IoC容器,利⽤依赖关系注⼊的⽅式,实现对象之间的解耦。
上述代码中,是通过构造函数的⽅式,把依赖对象注⼊到需要使⽤的对象中的
可以说,DI是IoC的⼀种实现

2.2 DI的方法使用

依赖注⼊是⼀个过程,是指IoC容器在创建Bean时,去提供运⾏时所依赖的资源,⽽资源指的就是对象.
在上⾯程序案例中,我们使⽤了 @Autowired 这个注解,完成了依赖注⼊的操作.
简单来说,就是把对象取出来放到某个类的属性中.
在⼀些⽂章中,依赖注⼊也被称之为"对象注⼊",“属性装配”,具体含义需要结合⽂章的上下⽂来理解
关于依赖注⼊,Spring也给我们提供了三种⽅式:

  1. 属性注⼊(FieldInjection)
  2. 构造⽅法注⼊(ConstructorInjection)
  3. Setter注⼊(SetterInjection)
属性注入

属性注⼊是使⽤ @Autowired 实现的,将Service类注⼊到Controller类中.
Service类的实现代码如下:

import org.springframework.stereotype.Service;
@Service
public class UserService {
		public void sayHi() {
			System.out.println("Hi,UserService");
		}
}
构造方法注入

构造⽅法注⼊是在类的构造⽅法中实现注⼊,如下代码所⽰:

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

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

Setter注入

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

@Controller
public class UserController3 {
	//注⼊⽅法3: Setter⽅法注⼊
	private UserService userService;


	@Autowired
	public void setUserService(UserService userService) {
		this.userService = userService;
	}
	
	
	public void sayHi(){
		System.out.println("hi,UserController3...");
		userService.sayHi();
	}
}
三种注入优缺点分析
  1. 属性注⼊

优点:简洁,使⽤⽅便;

缺点:

  • 只能⽤于IoC容器,如果是⾮IoC容器不可⽤,并且只有在使⽤的时候才会出现NPE(空指针异常)
  • 不能注⼊⼀个Final修饰的属性
  1. 构造函数注⼊

优点:

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

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

  1. Setter注⼊

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

缺点:

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

2.3 @Autowired存在的问题

当同⼀类型存在多个bean时,使⽤@Autowired会存在问题
报错的原因是,⾮唯⼀的Bean对象。
如何解决上述问题呢?Spring提供了以下⼏种解决⽅案:
• @Primary
• @Qualifier
• @Resource

@Primary

使⽤@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;
	}
	
	@Bean
	public User user2() {
		User user = new User();
		user.setName("lisi");
		user.setAge(19);
		return user;
	}
}
@Qualifier

使⽤@Qualifier注解:指定当前要注⼊的bean对象。在@Qualifier的value属性中,指定注⼊的bean
的名称。
• @Qualifier注解不能单独使⽤,必须配合@Autowired使⽤

@Controller
public class UserController {
	@Qualifier("user2") //指定bean名称
	@Autowired
	private User user;
	
	public void sayHi(){
		System.out.println("hi,UserController...");
		System.out.println(user);
	}
}
@Resource

使⽤@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);
	}
}

2.4 @Autowird的注入流程图

在这里插入图片描述

常见⾯试题:
@Autowird与@Resource的区别
• @Autowired是spring框架提供的注解,⽽@Resource是JDK提供的注解
• @Autowired默认是按照类型注⼊,⽽@Resource是按照名称注⼊.相⽐于@Autowired来说,
@Resource⽀持更多的参数设置,例如name设置,根据名称获取Bean。

三. 总结

Java Spring框架中的IoC(Inversion of Control,控制反转)和DI(Dependency Injection,依赖注入)是框架的核心概念之一,它们旨在降低组件之间的耦合度,提高代码的灵活性和可维护性。

  • 控制反转(IoC):在传统的程序设计中,应用程序控制程序的流程,即应用程序负责实例化和管理对象之间的依赖关系。而在IoC容器中,控制权被转移到容器,容器负责实例化对象并管理它们之间的依赖关系。这种控制权的转移使得组件之间的耦合度降低,提高了代码的灵活性和可测试性。

  • 依赖注入(DI):依赖注入是IoC的一种实现方式,通过依赖注入,容器会将一个对象所依赖的其他对象注入到该对象中,而不是由对象自己去创建或查找依赖的对象。依赖注入可以通过构造函数、属性或者方法进行注入,使得组件之间的依赖关系更加清晰、可控,同时也方便进行单元测试和替换依赖。

总的来说,IoC和DI通过将控制权交给容器,实现了组件之间的解耦和松耦合,提高了代码的可维护性、可测试性和可扩展性,是Spring框架的核心特性之一。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

12-2-CSS 字体图标

个人主页:学习前端的小z 个人专栏:HTML5和CSS3悦读 本专栏旨在分享记录每日学习的前端知识和学习笔记的归纳总结,欢迎大家在评论区交流讨论! 文章目录 CSS 字体图标1 字体图标的产生2 字体图标的优点3 字体图标的下载4 字体图标的…

LangChain-10(2) 加餐 编写Agent获取本地Docker运行情况 无技术含量只是思路

可以先查看 上一节内容,会对本节有更好的理解。 安装依赖 pip install langchainhub编写代码 核心代码 tool def get_docker_info(docker_name: str) -> str:"""Get information about a docker pod container info."""result…

隐私计算实训营学习八:隐语SCQL的开发实践

文章目录 一、SCQL使用集成最佳实践1.1 SCQL使用流程1.2 SCQL部署1.3 SCQL使用示例 二、SCQL工作原理三、使用SecretNote上手体验SCQL 一、SCQL使用集成最佳实践 1.1 SCQL使用流程 SCQL使用: SCQL 开放 API 供⽤户使⽤/集成。可以使⽤SCDBClient上⼿体验(类似与My…

归一化技术比较研究:Batch Norm, Layer Norm, Group Norm

归一化层是深度神经网络体系结构中的关键,在训练过程中确保各层的输入分布一致,这对于高效和稳定的学习至关重要。归一化技术的选择(Batch, Layer, GroupNormalization)会显著影响训练动态和最终的模型性能。每种技术的相对优势并…

CSS - 你实现过宽高自适应的正方形吗

难度 难度级别:中高级及以上 提问概率:80% 宽高自适应的需求并不少见,尤其是在当今流行的大屏系统开发中更是随处可见,很显然已经超越了我们日常将div写死100px这样的范畴,那么如何实现一个宽高自适应的正方形呢?这里提出两种实现方案。…

【Linux】进程初步理解

个人主页 : zxctscl 如有转载请先通知 文章目录 1. 冯诺依曼体系结构1.1 认识冯诺依曼体系结构1.2 存储金字塔 2. 操作系统2.1 概念2.2 结构2.3 操作系统的管理 3. 进程3.1 进程描述3.2 Linux下的PCB 4. task_struct本身内部属性4.1 启动4.2 进程的创建方式4.2.1 父…

JAVA:探索Apache POI 处理利器

请关注微信公众号:拾荒的小海螺 1、简述 Apache POI是Apache软件基金会的顶级项目之一,它允许Java开发人员读取和写入Microsoft Office格式的文档,包括Excel、Word和PowerPoint文件。通过POI,开发人员可以创建、修改和读取Excel…

面试(04)————JavaWeb

1、网络通讯部分 1.1、 TCP 与 UDP 区别? 1.2、什么是 HTTP 协议? 1.3、TCP 的三次握手,为什么? 1.4、HTTP 中重定向和请求转发的区别? 1.5、 Get 和 Post 的区别? 2、cookie 和 session 的区别&am…

加入酷开会员 酷开系统带你一起开启看电视的美好时光!

看电视对孩子和大人来说,都是有好处的。英国的《星期日泰晤士报》曾刊登报道:“看电视可以让小孩增长见闻,学习各种良好的社交和学习技巧,从而为他们今后的学习打下良好的基础。”而对于成年人来说,看电视也是一种娱乐…

linux 安装 pptp 协议

注意:目前iOS已不支持该协议 yum -y install ppp wget https://download-ib01.fedoraproject.org/pub/epel/7/x86_64/Packages/p/pptpd-1.4.0-2.el7.x86_64.rpm yum -y install pptpd-1.4.0-2.el7.x86_64.rpm vi /etc/pptpd.conf 去除 localip 和 remoteip的注释 …

【.Net】Polly

文章目录 概述服务熔断、服务降级、服务限流、流量削峰、错峰、服务雪崩Polly的基本使用超时策略悲观策略乐观策略 重试策略请求异常响应异常 降级策略熔断策略与策略包裹(多种策略组合) 参考 概述 Polly是一个被.NET基金会支持认可的框架,同…

SAP-MM 新增公司代码 激活物料分类账

1、OMX1 - 激活物料分类账(配置环境) 2、CKMSTART - 物料分类账的生产开始(生产机运行) 不激活创建物料时会报错:估价范围还没有生产式的物料账簿 执行后结果: 以上~~

creo扫描杯子学习笔记

creo扫描杯子学习笔记 扫描2要素: 轨迹, 截面。 多用于曲线扫描,区别于拉伸命令。 大小自定 旋转扫描 抽壳 草绘把手 扫描把手 复制曲面 实例化切除 成型

Web爬虫

📑前言 本文主要是【Web爬虫】——简单使用的文章,如果有什么需要改进的地方还请大佬指出⛺️ 🎬作者简介:大家好,我是听风与他🥇 ☁️博客首页:CSDN主页听风与他 🌄每日一句&#…

PHP实现网站微信扫码关注公众号后自动注册登陆实现方法及代码【关注收藏】

在网站注册登陆这环节,增加微信扫码注册登陆,普通的方法需要开通微信开发者平台,生成二维码扫码后才能获取用户的uinonid或openid,实现注册登陆,但这样比较麻烦还要企业认证交费开发者平台,而且没有和公众号…

区域自动气象站讲解

TH-QC10当我们每天查看天气预报,安排出行计划,或是在户外活动时关注天气变化,很少有人会想到这一切背后默默付出的“英雄”——区域自动气象站。这些看似不起眼的气象监测设备,却在我们日常生活中扮演着至关重要的角色。今天&…

【话题】程序员35岁会失业吗?

大家好,我是全栈小5,欢迎阅读小5的系列文章,这是《话题》系列文章 目录 背景招聘分析一、技术更新换代的挑战二、经验与技术的双重优势三、职业发展的多元化选择四、个人成长与职业规划的平衡五、结语文章推荐 背景 35岁被认为是程序员职业生…

【OJ】stack刷题

个人主页 : zxctscl 如有转载请先通知 题目 1. 155. 最小栈1.1 分析1.2 代码 2. JZ31 栈的压入、弹出序列2.1 分析2.2 代码 3. 150. 逆波兰表达式求值3.1 分析3.2 代码 1. 155. 最小栈 1.1 分析 利用两个栈,一个栈a负责入数据和出数据,另一个…

分类预测 | Matlab实现DRN深度残差网络数据分类预测

分类预测 | Matlab实现DRN深度残差网络数据分类预测 目录 分类预测 | Matlab实现DRN深度残差网络数据分类预测分类效果基本介绍程序设计参考资料 分类效果 基本介绍 1.Matlab实现DRN深度残差网络数据分类预测(完整源码和数据),运行环境为Matl…

合宙开发板Core_Air780E测试AT指令

一、官方资料 CORE-AIR780E 开发板是合宙通信推出的基于 Air780E 模组所开发的,包含电源,SIM 卡,USB,天线,音频等必要功能的最小硬件系统。以方便用户在设计前期对 Air780E 模块 进行性能评估,功能调试&…