《JavaEE进阶》----12.<SpringIOCDI【扫描路径+DI详解+经典面试题+总结】>

news/2024/9/16 15:15:51/ 标签: java-ee, java, Spring IoC, Spring DI, Spring

本篇博客主要讲解

扫描路径

DI详解:三种注入方式及优缺点

经典面试题

总结

五、环境扫描路径

虽然我们没有告诉Spring扫描路径是什么,但是有一些注解已经告诉Spring扫描路径是什么了

如启动类注解@SpringBootApplication。

里面有一个注解是@componentScan这个注解就是扫描路径注解。

默认扫描路径

默认为:启动类所在的路径

被@componentScan标识的当前类所在的路径。

而启动类@SpringBootApplication包含了@componentScan。因此也是被@SpringBootApplication标识的类。

注:

这五大注解必须在Spring的扫描路径下才会生效。

java">package com.qiyangyang.iocdome;

因此

我们这个项目Spring的扫描路径是com.qiyangyang.iocdome这个路径。

因此,当我们移动IocDomeApplication这个类到不同的文件中。Spring的默认扫描路径就会发生改变。

我们通常把启动类放在最外层(Controller、Service...的上一层)。这样就可以扫描到使用IoC的类了。如果非要放在别的地方。你希望它扫描哪些路径,你也可以指定。

指定扫描路径

我们也可以通过 @ComponentScan注解 指定扫描路径

指定方法:在启动类上面加上如下注解

扫描路径的起始文件地址是java文件的下一级目录。

java">@ComponentScan(“扫描路径”)

eg:

java">@ComponentScan(“com.qiyangyang.iocdome”)

如果什么都没加,默认为被该注解标识的所在的类的路径。

六、依赖注入(DI)详解

DI(Dependency-Injection依赖注入)

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

程序运⾏时需要某个资源,此时容器就为其提供这个资源. 从这点来看, 依赖注⼊(DI)和控制反转(IoC)是从不同的⻆度的描述的同⼀件事情,就是指通过 引入IoC容器,利用依赖关系注入的方式,实现对象之间的解耦。

依赖注入是⼀个过程,是指IoC容器在创建Bean时,去提供运行时所依赖的资源,而资源指的就是对象. 在下面程序案例中

我们使用了 @Autowired 这个注解,完成了依赖注⼊的操作. 简单来说,就是把对象取出来放到某个类的属性中.。在一些文章中。依赖注⼊也被称之为"对象注入","属性装配",

具体含义需要结合文章的上下文来理解

关于依赖注入,Spring也给我们提供了三种方式:

6.1 @Autowired属性注入(Field-Injection)

这个方法我们在上一篇文章使用过。这是重述一遍

java">@RestController
@RequestMapping("/book")
public class BookController {
//属性注入@Autowiredprivate BookService bookService;
}

由于BookService类已经被@Service注解过。因此已经将BookService类的对象存入了Spring容器

在我们后续使用它的对象的时候。不需要我们自己new这个对象。而是可以通过如上定义一个BookService属性。通过@Autowired注解,将这个对象取出。这样后续就可以直接用这个对象 

 

6.2 构造方法注入(Constructor-Injection)

注:当我们手动加上构造函数之后。一定要养成习惯把默认无参构造方法写上

当有单个构造函数

Spring知道使用哪个。因此会正常运行。

java">  
@RestController
@RequestMapping("/book")
public class BookController {
//构造方法注入private BookService bookService;public BookController(BookService bookService){this.bookService = bookService;}
java">@Controller("bean") //创建对象  //括号中是对bean进行重命名 如果没有指定名称spring帮我们指定
public class UserController {private UserService userService;private UserRepository userRepository;public UserController(UserService userService, UserRepository userRepository) {this.userService = userService;this.userRepository = userRepository;}public void say(){userService.say();userRepository.say();System.out.println("Hi Controller!!!");}
}

 

当有多个构造函数

java">@Controller("bean") //创建对象  //括号中是对bean进行重命名 如果没有指定名称spring帮我们指定
public class UserController {private UserService userService;private UserRepository userRepository;public UserController(){}public UserController(UserRepository userRepository) {this.userRepository = userRepository;}public UserController(UserService userService, UserRepository userRepository) {this.userService = userService;this.userRepository = userRepository;}public void say(){userService.say();userRepository.say();System.out.println("Hi Controller!!!");}
}

 优先使用默认无参构造函数。如果没有。就会报错。

 @Autowired 指定使用某个构造函数:

java">    @Autowiredpublic UserController(UserService userService, UserRepository userRepository) {this.userService = userService;this.userRepository = userRepository;}

 

6.3 Setter 注入(SetterInjection)

 也需要搭配@AutoWired注解才可以正常注入。

java">private UserService userService;
private UserRepository userRepository;
@Autowired
public void setUserService(UserService userService) {this.userService = userService;
}
@Autowired
public void setUserRepository(UserRepository userRepository) {this.userRepository = userRepository;
}

6.3三种依赖注入优缺点

属性注入(Spring最不推荐,但没关系):

优点:

简介,使用方便;

缺点:

1.只能用于 IoC 容器。因为它是Spring提供的。

若不是 IoC 容器不可用,且只有在使用的时候才会出现 NPE(空指针异常)

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

构造方法注入(Spring4.x推荐):

我们可以点进@Autowired注解。再点击目录。看到我们现在使用的Spring版本。

优点:

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

注:final修饰的属性有一个要求,需要满足下列任意条件

①声明时,要完成初始化

②在构造函数中进项赋值。

2.注入的对象不会被修改

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

4.通用性好。构造方法是JDK支持的,所以更换任何框架他都适用。

缺点:

1.注入多个对象时,代码会比较繁琐。

Setter注入(Spring3.x推荐)

优点:

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

缺点:

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

2.注入对象可能会被改变。因为setter方法可能会被多次调用。就有被修改的风险。

6.4@AutoWired存在的问题

当同一类型存在多个Bean时。使用@Autowired会存在问题

java">@Configuration
public class BeanConfig {@Beanpublic UserInfo userInfo1(){UserInfo userInfo = new UserInfo();userInfo.setId(120);userInfo.setName("张三");userInfo.setAge(18);return userInfo;}@Beanpublic UserInfo userInfo2(){UserInfo userInfo2 = new UserInfo();userInfo2.setId(121);userInfo2.setName("李四");userInfo2.setAge(28);return userInfo2;}
}

报错的原因是非唯一Bean对象。

Spring提供了一下几种解决方案。

@Primary

在构造多个对象时

使用@Primary注解:当存在多个相同类型的Bean注入时,加上@Primary注解,来确定默认的实现。

java">@Configuration
public class BeanConfig {@Primary@Beanpublic UserInfo userInfo1(){UserInfo userInfo = new UserInfo();userInfo.setId(120);userInfo.setName("张三");userInfo.setAge(18);return userInfo;}@Beanpublic UserInfo userInfo2(){UserInfo userInfo2 = new UserInfo();userInfo2.setId(121);userInfo2.setName("李四");userInfo2.setAge(28);return userInfo2;}
}

这样就不会报错了。也就是默认使用张三这个对象进行使用。

@Qualifier

使用@Qualifier注解:在注入时。指定当前要注入的bean对象。在@Qualifier的value属性中,指定注入的bean 的名称。

@Qualifier注解不能单独使用,必须配合@Autowired使用

java">    @Qualifier("userInfo2")//指定bean的名称@Autowiredprivate UserInfo userInfo;public void say(){System.out.println("Hi Controller!!!");userService.say();System.out.println(userInfo);}

@Resource

使用@Resource注解:是按照bean的名称进行注入。通过name属性指定要注入的bean的名称。

不用@Autowirede注解配合使用。

java">    @Resource(name="userInfo2")private UserInfo userInfo;public void say(){System.out.println("Hi Controller!!!");userService.say();System.out.println(userInfo);}


常见面试题:

1.@Autowird与@Resource的区别

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

• @Autowired 默认是按照类型注入,@Resource是按照名称注入,相比于@Autowired来说, @Resource支持更多的参数设置,例如 name 设置,根据名称获取 Bean。 

2.SpringSpringBoot,SpringMVC之间的区别和联系,你是如何理解的?

我的理解

1.Spring(很早) 简单来说,Spring是一个轻量级、一站式、模块化的开发应用框架。主要用于简化企业级应用程序开发。

Spring的主要功能:管理对象,以及对象之间的依赖关系。面向切面编程、数据库事务管理、数据访问、web框架支持等。

Spring(这里指Spring-core。Spring家族都具有高度可开放性)具备高度可开放性。并不强制依赖Spring,开发者可以自由选择Spring的部分或者全部,Spring可以无缝集成第三方框架。比如数据访问框架(Hibernate、JPA)、web框架(如Struts、JSF)。

在使用Spring时,不强制使用Spring框架,也可以使用第三方框架。

2.SpringBoot(晚) 是对Spring的一个封装,为简化Spring应用的开发而出现的。中小型企业。没有成本研究自己的框架,使用SpringBoot可以快速的搭建框架,降低开发成本。让开发人员更加专注于Spring应用的开发。而无需过多关注xml的配置和一些底层实现。

SpringBoot是一个手脚架,插拔式搭建项目,可以快速的集成其他框架进来。

比如想使用SpringBoot开发Web项目,只需要引入SpringMVC即可。Web开发的工作是SpringMVC完成的。而不是SpringBoot。想完成数据访问,只需要引入Mybatis框架即可。

SpringBoot只是辅助简化项目开发的,让开发变得更简单,甚至不需要额外的web服务器,直接生产jar包执行即可。

使我们在创建项目的时候可以直接添加一些依赖。并且内置web服务器、提供许多注解方便我们书写代码。对项目进行更多的监控指标,更好的了解项目的运行情况。简化我们的开发。

3.SpringMVC(早) 是一个Spring家族的子框架。是针对Web开发和网络接口的一种MVC的思想的实现。也被称作Spring Web MVC(Spring Web)。

在创建项目时,我们添加的依赖Spring Web实际上引的就是SpringMVC。可以认为Spring给我们提供的Web功能就叫做SpringMVC。

我们现在认为SpringMVC就是SpringWeb。主要进行Web开发(网站开发)。

最后一句总结:Spring MVC和Spring Boot都属于SpringSpring MVC是基于Spring的一个MVC框架。而Spring Boot是基于Spring的一套快速开发整合包

比如我们的图书系统代码中

整体框架是通过SpringBoot搭建的

IoC、DI功能是Spring的提供的,

web相关功能是Spring MVC提供的。

这三者专注的领域不同,解决的问题也不⼀样,总的来说,Spring就像一个大家族,有众多衍生产 品,但他们的基础都是Spring,用一张图来表他们三个的关系:

假如把Spring看作火车。(而做项目相当于坐火车) 但是它买票不方便。 

因此就可以把SpringBoot看作是12306。而12306不仅可以订票还可以订酒店。打的等等。让我们坐火车(做项目更加的方便)

SpringMVC 可以认为是火车里面提供的一些功能。比如买票,改签,插座等等。(注解/Cookie&Session)

3.ApplicationContext VS BeanFactory

1.继承关系和功能方面来说:

Spring 容器有两个顶级的接口:BeanFactory和 ApplicationContext。其中BeanFactory提供了基础的访问容器的能力,而ApplicationContext 属于BeanFactory的⼦类,它除了继承了BeanFactory的所有功能之外, 它还拥有独特的特性,还添加了对国际化支持、资源访问支持、以及事件传播等方面的支持.

2.从性能方面来说:

ApplicationContext 是⼀次性加载并初始化所有的 Bean 对象,而BeanFactory 是需要那个才去加载那个,因此更加轻量. (空间换时间) 

4.三种依赖注入优缺点

属性注入(Spring最不推荐,但没关系):

优点:

简介,使用方便;

缺点:

1.只能用于 IoC 容器。因为它是Spring提供的。

若不是 IoC 容器不可用,且只有在使用的时候才会出现 NPE(空指针异常)

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

构造方法注入(Spring4.x推荐):

我们可以点进@Autowired注解。再点击目录。看到我们现在使用的Spring版本。

优点:

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

注:final修饰的属性有一个要求,需要满足下列任意条件

①声明时,要完成初始化

②在构造函数中进项赋值。

2.注入的对象不会被修改

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

4.通用性好。构造方法是JDK支持的,所以更换任何框架他都适用。

缺点:

1.注入多个对象时,代码会比较繁琐。

Setter注入(Spring3.x推荐)

优点:

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

缺点:

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

2.注入对象可能会被改变。因为setter方法可能会被多次调用。就有被修改的风险。

5.常见注解有哪些?分别是什么作用?

1. web url映射: @RequestMapping

2.参数接收和接口响应:@RequestParam,@RequestBody,@ResponseBody

3.bean的存储:@Controller,@Service,@Repository,@Component,@Configuration,@Bean

4.bean的获取: @Autowired, @Qualifier, @Resource

5.多个bean的默认指定:@Primary

6.Spring两大核心思想IOC和AOP

待续


总结:

告诉spring管理Bean,Bean的存储

1.类注解:五大注解@Controller@Component@Configuration@Service@Repository

2.方法注解:@Bean

Bean的名称:

1.五大注解

类名首字母小写,如果前两位字母均为大写,则为原类名,也可以指定Bean的名称

指定方法:@Controller(“beanName”)

2.@bean

默认名称是方法名,也可以指定名称:@Bean(“beanName”)

使用场景

1.五大注解 自己开发的程序

2.@Bean

①存储第三方的对象(代码不在自己的项目中)

②一个类型需要创建多个对象时

获取bean三种扫描路径的方式

通过Spring运行环境的Spring上下文 

java">ApplicationContext context = SpringApplication.run(IocDomeApplication.class, args);

获取Bean的功能是BeanFeactory提供的 

三种方式

1.通过类型

java">UserController bean1 = context.getBean(UserController.class);
bean1.say();

2.通过bean名称

java">UserService userService =(UserService) context.getBean("userService");
userService.say();

3.通过bean名称+类型

java">UserComponent userComponent = context.getBean("userComponent", UserComponent.class);
userComponent.say();

扫描路径:

默认扫描路径:启动类所在的路径

指定扫描路径: 在启动类上面加上如下注解

java">@ComponentScan(“扫描路径”)


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

相关文章

移动应用门户实现的技术方案

移动应用门户是专为移动设备(如智能手机和平板电脑)设计的应用程序,比如:小程序、APP等,用户可以通过应用商店下载并安装。这些应用程序提供了更好的用户体验,通常具有更高的性能和交互性,可以直…

数据结构的简单认识

数据结构是计算机存储、组织数据的方式。它可以分为逻辑结构和物理结构。 逻辑结构主要有集合、线性结构、树形结构和图形结构。集合中的数据元素间除“同属于一个集合”外,无其他关系;线性结构的数据元素之间存在一对一的关系,如链表、栈和队…

linux系统中,计算两个文件的相对路径

realpath --relative-to/home/itheima/smartnic/smartinc/blocks/ruby/seanet_diamond/tb/parser/test_parser_top /home/itheima/smartnic/smartinc/corundum/fpga/lib/eth/lib/axis/rtl/axis_fifo.v 检验方式就是直接在当前路径下,把输出的路径复制一份&#xff0…

Java | Leetcode Java题解之第386题字典序排数

题目&#xff1a; 题解&#xff1a; class Solution {public List<Integer> lexicalOrder(int n) {List<Integer> ret new ArrayList<Integer>();int number 1;for (int i 0; i < n; i) {ret.add(number);if (number * 10 < n) {number * 10;} els…

【RabbitMQ】基本概念以及安装教程

1. 什么是MQ MQ( Message queue),从字面意思上看,本质是个队列,FIFO 先入先出&#xff0c;只不过队列中存放的内容是消息(message)而已.消息可以非常简单,比如只包含文本字符串,JSON等,也可以很复杂,比如内嵌对象.MQ多用于分布式系统之间进行通信 系统之间的调用通常有两种方式…

揭秘 AMD GPU 上 PyTorch Profiler 的性能洞察

Unveiling performance insights with PyTorch Profiler on an AMD GPU — ROCm Blogs 2024年5月29日&#xff0c;作者&#xff1a;Phillip Dang。 在机器学习领域&#xff0c;优化性能通常和改进模型架构一样重要。在本文中&#xff0c;我们将深入探讨 PyTorch Profiler&#…

基于深度学习的结构优化与生成

基于深度学习的结构优化与生成技术应用于多种领域&#xff0c;例如建筑设计、机械工程、材料科学等。该技术通过使用深度学习模型分析和优化结构形状、材料分布、拓扑结构等因素&#xff0c;旨在提高结构性能、减少材料浪费、降低成本、并加快设计流程。 1. 结构优化与生成的核…

从零开始写论文:如何借助ChatGPT生成完美摘要?

AIPaperGPT&#xff0c;论文写作神器~ https://www.aipapergpt.com/ 在写论文的过程中&#xff0c;摘要是一个非常重要的部分&#xff0c;它能够帮助读者快速理解论文的核心内容&#xff0c;决定是否进一步阅读全文。但是许多学生在写摘要的时候常常感到困惑&#xff0c;不知…

怎么仿同款小程序的开发制作方法介绍

很多老板想要仿小程序系统&#xff0c;就是想要做个和别人界面功能类似的同款小程序系统&#xff0c;咨询瀚林问该怎么开发制作&#xff1f;本次瀚林就为大家介绍一下仿制同款小程序系统的方法。 1、确认功能需求 想要模仿同款小程序系统&#xff0c;那么首先需要找到自己想要…

24/9/3算法笔记 kaggle泰坦尼克

题目&#xff1a; 这次我用两种算法做了这道题 逻辑回归二分类算法 import pandas as pd from sklearn.model_selection import train_test_split from sklearn.preprocessing import StandardScaler from sklearn.linear_model import LogisticRegression from sklearn.metr…

CentOS 常用指令及作用解析

CentOS 常用指令及作用解析 在使用CentOS操作系统时&#xff0c;了解并熟练掌握常用的Linux指令是非常重要的。这些指令可以帮助你进行文件管理、系统管理、网络管理等操作。本篇文章将介绍一些CentOS下常用的指令及其主要作用。 目录 文件和目录操作指令文件内容操作指令系…

5千多道安全生产证考试题库ACCESS\EXCEL数据库

安全生产是保护劳动者的安全、健康和国家财产&#xff0c;促进社会生产力发展的基本保证&#xff0c;也是保证社会主义经济发展&#xff0c;进一步实行改革开放的基本条件。因此&#xff0c;做好安全生产工作具有重要的意义。今天的数据即是安全生产资格证、许可证考试题库。 大…

Unity --- 各种关节(Joints)来模拟物体之间的连接

目录 一:2D关节 一:1 固定关节 (Fixed Joint 2D) 功能: 适用场景: 1. 平台游戏中的固定平台: 2. 拼图游戏中的固定部件: 3. 建筑游戏中的固定结构: 一:2 铰链关节 (Hinge Joint 2D) 功能: 适用场景: 一:3 弹簧关节 (Spring Joint 2D) 功能: 适用场景: 1. …

【系统架构设计师】命令行风格

命令行风格(Command Line Interface, CLI)是一种用户与计算机程序交互的方式,它主要通过文本命令来执行程序的功能。在这种风格中,用户通过键盘输入命令,程序则通过命令行界面(通常是终端或控制台窗口)显示输出和反馈信息。命令行风格因其高效、灵活和强大的功能而广泛应…

Spring2~~~

注解配置Bean Spring的 IOC 容器检查到注解就会生成对象&#xff0c;但这个注解的具体含义不会识别 配置自动扫描的包 <!--配置容器要扫描的包1. component-scan 要对指定包下的类进行扫描, 并创建对象到容器2. base-package 指定要扫描的包3. 含义是当spring容器创建/初始…

在 Go 语言中使用模块

模块很重要,因为它们允许将相关的代码文件组织到同一个包中,并以一种提高简单性和可重复性的方式组织代码。 1. 开始使用模块 从代码的角度看,模块是 Go 包和文件以及名为 go.mod 的文件的集合。在接下来的步骤中,将学习如何创建模块,然后使用它。 2. 第一步:创建项目目…

MATLAB绘图基础5:MATLAB数据导入

参考书&#xff1a;《 M A T L A B {\rm MATLAB} MATLAB与学术图表绘制》(关东升)。 5.MATLAB数据导入 5.1 从CSV文件读取数据 C S V {\rm CSV} CSV文件是一种纯文本文件&#xff0c;文件中的数据以逗号为分隔符进行字段分隔&#xff0c;每一行数据代表一条记录&#xff0c;每…

力扣416-分割等和子集(Java详细题解)

题目链接&#xff1a;416. 分割等和子集 - 力扣&#xff08;LeetCode&#xff09; 前情提要&#xff1a; 因为本人最近都来刷dp类的题目所以该题就默认用dp方法来做。 最近刚学完01背包&#xff0c;所以现在的题解都是以01背包问题为基础再来写的。 如果大家不懂01背包的话…

人生苦短我用Python Excel文件基本操作

人生苦短我用Python Excel文件基本操作 前言文件基本操作的模块和类pathlib.Path 类os.stat_result 类time.struct_time 命名元组time 模块shutil 模块 示例查看属性拷贝文件重命名文件查找文件批量操作 测试 前言 本文主要介绍通过Python中的pathlib模块&#xff0c;完成Exce…

【Android面试八股文】你能说说FragmentPagerAdapter 和 FragmentStatePagerAdapter的区别吗?

文章目录 一、FragmentPagerAdapter1.1 工作方式1.2 生命周期1.3 优缺点1.4 适用场景1.5 示例二、FragmentStatePagerAdapter2.1 工作方式2.2 生命周期2.3 优缺点2.4 适用场景2.4 示例三、FragmentPagerAdapter和FragmentStatePagerAdapter关于instantiateItem()方法和destroyI…