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

news2024/9/20 1:03:40

本篇博客主要讲解

扫描路径

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

经典面试题

总结

五、环境扫描路径

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

如启动类注解@SpringBootApplication。

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

默认扫描路径

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

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

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

注:

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

package com.qiyangyang.iocdome;

因此

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

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

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

指定扫描路径

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

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

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

@ComponentScan(“扫描路径”)

eg:

@ComponentScan(“com.qiyangyang.iocdome”)

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

六、依赖注入(DI)详解

DI(Dependency-Injection依赖注入)

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

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

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

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

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

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

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

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

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

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

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

 

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

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

当有单个构造函数

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

  
@RestController
@RequestMapping("/book")
public class BookController {
//构造方法注入
      private BookService bookService;
      public BookController(BookService bookService){
          this.bookService = bookService;
    }
@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!!!");
    }
}

 

当有多个构造函数

@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 指定使用某个构造函数:

    @Autowired
    public UserController(UserService userService, UserRepository userRepository) {
        this.userService = userService;
        this.userRepository = userRepository;
    }

 

6.3 Setter 注入(SetterInjection)

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

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会存在问题

@Configuration
public class BeanConfig {
    @Bean
    public UserInfo userInfo1(){
        UserInfo userInfo = new UserInfo();
        userInfo.setId(120);
        userInfo.setName("张三");
        userInfo.setAge(18);
        return userInfo;
    }

    @Bean
    public UserInfo userInfo2(){
        UserInfo userInfo2 = new UserInfo();
        userInfo2.setId(121);
        userInfo2.setName("李四");
        userInfo2.setAge(28);
        return userInfo2;
    }
}

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

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

@Primary

在构造多个对象时

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

@Configuration
public class BeanConfig {
    @Primary
    @Bean
    public UserInfo userInfo1(){
        UserInfo userInfo = new UserInfo();
        userInfo.setId(120);
        userInfo.setName("张三");
        userInfo.setAge(18);
        return userInfo;
    }

    @Bean
    public UserInfo userInfo2(){
        UserInfo userInfo2 = new UserInfo();
        userInfo2.setId(121);
        userInfo2.setName("李四");
        userInfo2.setAge(28);
        return userInfo2;
    }
}

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

@Qualifier

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

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

    @Qualifier("userInfo2")//指定bean的名称
    @Autowired
    private UserInfo userInfo;


    public void say(){
        System.out.println("Hi Controller!!!");
        userService.say();
        System.out.println(userInfo);
    }

@Resource

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

不用@Autowirede注解配合使用。

    @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.Spring,SpringBoot,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都属于Spring。Spring 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上下文 

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

获取Bean的功能是BeanFeactory提供的 

三种方式

1.通过类型

UserController bean1 = context.getBean(UserController.class);
bean1.say();

2.通过bean名称

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

3.通过bean名称+类型

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

扫描路径:

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

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

@ComponentScan(“扫描路径”)

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

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

相关文章

【Leetcode152】乘积最大子数组(动态规划)

文章目录 一、题目二、思路三、代码 一、题目 二、思路 (0)读懂题意:题目的“连续”是指位置的连续,而不是说数字的连续,这是个大坑。 (1)确定状态:定义两个状态来记录当前子数组的…

Windows本地制作nginx证书

OpenSSL 是一个用于生成和管理 SSL/TLS 证书的工具。下载并安装 OpenSSL Select Additional Tasks页面勾选 The OpenSSL binaries (/bin) directory 将OpenSSL的bin目录配置到path中 开命令提示符(cmd)或 PowerShell。运行以下命令生成一个新的私钥和自…

哈希表的封装和位图

文章目录 2 封装2.1 基础框架2.2 迭代器(1)2.3 迭代器(2) 3. 位图3.1 问题引入3.2 左移和右移?3.3 位图的实现3.4 位图的题目3.5 位图的应用 2 封装 2.1 基础框架 文章 有了前面map和set封装的经验,容易写出下面的代码 // UnorderedSet.h #pragma on…

WireShark抓包软件介绍和安装

文章目录 一、WireShark软件介绍1. **概述**2. **主要功能**3. **使用场景**4. **安装和使用**5. **优点和限制**6. **结论** 二、WireShark的安装三、WireShark的基本使用1. **混杂模式(Promiscuous Mode)****概述****工作原理****应用场景****启用方式…

STM32F407VET6开发板RT-Thread memheap 内存堆的适配

相关文章 STM32F407VET6开发板RT-Thread的移植适配 STM32F407VET6开发板RT-Thread MSH 串口的适配 环境 STM32F407VET6 开发板(魔女),http://www.stm32er.com/ Keil MDK5,版本 5.36 memheap 内存堆 RT-Thread 支持 memheap …

数据结构基础讲解(二)——线性表之单链表专项练习

本文数据结构讲解参考书目: 通过网盘分享的文件:数据结构 C语言版.pdf 链接: https://pan.baidu.com/s/159y_QTbXqpMhNCNP_Fls9g?pwdze8e 提取码: ze8e 上一节我讲了线性表中顺序表的定义以及常用的算法,那么这节我将继续讲解顺序表中的链式…

MySQL-CRUD入门1

文章目录 认识配置文件client节点mysql节点mysqld节点 数据的添加(Create)添加一行数据添加多行数据两种添加数据的效率对比 数据的查询(Retrieve)全列查询指定列查询查询中带有表达式关于字面量关于as重命名 临时表引入distinct去重order by 排序关于NULL 认识配置文件 在我们…

数据结构基础详解(C语言): 树与二叉树的应用_哈夫曼树与哈夫曼曼编码_并查集_二叉排序树_平衡二叉树

文章目录 树与二叉树的应用1.哈夫曼树与哈夫曼曼编码1.1 带权路径长度1.2 哈夫曼树1.2.1 哈夫曼树的构造1.3 哈夫曼编码 2.并查集2.1 并查集的三要素2.1.1 并查集的逻辑结构2.1.2 并查集的存储结构 2.2 并查集的优化2.2.1 初步优化(并操作优化)2.2.2 终极…

flink wordcount

Maven配置pom文件 <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0"xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation"http://maven.apache.org/P…

mybatis-plus使用@EnumValue搭配shardingsphere报错“getObject with type”

目录 一、背景二、修改方案三、如何让修改的TypeHandler生效1、在TableField中配置TypeHandler2、考虑直接在TypeHandlerRegistry注册该枚举的handler为自定义的handler处理类。3、不止重写MybatisEnumTypeHandler&#xff0c;还重写CompositeEnumTypeHandler类3.1、修改Compos…

【WPF】桌面程序开发之xaml页面主题和样式详解

使用Visual Studio开发工具&#xff0c;我们可以编写在Windows系统上运行的桌面应用程序。其中&#xff0c;WPF&#xff08;Windows Presentation Foundation&#xff09;项目是一种常见的选择。然而&#xff0c;对于初学者来说&#xff0c;WPF项目中xaml页面的布局设计可能是一…

Bat的退役前

我们很讨厌bat 语法这版的命令形式后缀尽管古老&#xff0c;可是在涉及细微VS 项目op 时候&#xff0c;它起到了不可忽视且非它不行的效应 我们不想替历史背上厚重的学习包袱&#xff0c;可是我们能忽视BAT 吗 如若进入到 无window时代&#xff0c;我们几乎得全然依仗BAT专家。…

35天学习小结

距离上次纪念日&#xff0c;已经过去了35天咯 算算也有5周了&#xff0c;在这一个月里&#xff0c;收获的也挺多&#xff0c;在这个过程中认识的大佬也是越来越多了hh 学到的东西&#xff0c;其实也没有很多&#xff0c;这个暑假多多少少还是有遗憾的~ 第一周 学习了一些有…

【计算机组成原理】详细解读带符号整数的原码表示法

带符号整数的表示——原码 导读一、有符号整数的存储结构二、有符号整数的表现形式三、原码3.1 原码与真值之间的转换3.2 原码的运算3.3 原码的优缺点 结语 导读 大家好&#xff0c;很高兴又和大家见面啦&#xff01;&#xff01;&#xff01; 在上一篇内容中我们介绍了无符号…

828华为云征文|基于华为云Flexus云服务器X搭建jumpserver堡垒机软件

文章目录 ❀前言❀jumpserver堡垒机概述❀环境准备❀部署说明❀在线安装❀浏览器访问❀资产添加❀资产授权❀资产登录❀总结 ❀前言 近期华为云推出了最新的华为云Flexus云服务器X&#xff0c;这款云主机在算柔性算力做出了重大变革。华为云Flexus云服务器X基于擎天QingTian架…

Xilinx FPGA 原语解析(二):IBUFDS差分输入缓冲器(示例源码及仿真)

目录 前言&#xff1a; 一、原语使用说明 二、原语实例化代码模版 三、使用示例 1.设计文件代码 2.仿真文件代码 3.仿真结果 前言&#xff1a; 本文主要参考资料xilinx手册&#xff0c;《Xilinx 7 Series FPGA and Zynq-7000 All Programmable SoC Libraries Guide for…

LeetCode 热题 100 回顾1

干货分享&#xff0c;感谢您的阅读&#xff01;原文见&#xff1a;LeetCode 热题 100 回顾_力code热题100-CSDN博客 一、哈希部分 1.两数之和 &#xff08;简单&#xff09; 题目描述 给定一个整数数组 nums 和一个整数目标值 target&#xff0c;请你在该数组中找出 和为目标…

【Python 千题 —— 算法篇】词频统计

Python 千题持续更新中 …… 脑图地址 👉:⭐https://twilight-fanyi.gitee.io/mind-map/Python千题.html⭐ 题目背景 在日常开发和文本处理工作中,单词计数是一个非常基础但又极为重要的操作。无论是统计一篇文章的词频,还是分析一段文本的关键词,单词计数都起着关键作用…

Spring Boot 集成 MinIO 与 KKFile 实现文件预览功能

文件预览功能是提升用户体验的重要部分,尤其是在文档管理系统中。本文将带你逐步实现如何在 Spring Boot 项目中集成 MinIO(一个对象存储系统)与 KKFileView(一个开源文件预览工具),以实现对各种类型文件的在线预览 项目准备 Java 11+ Spring Boot MinIO 服务器 KKFileV…

C语言 ——— 带副作用的宏参数

目录 带有副作用的代码 带有副作用的宏参数 结论 带有副作用的代码 代码演示&#xff1a; int a 10;int b a; 副作用解析&#xff1a; 变量 a 在赋值给 b 之前 a 的值自增了1&#xff0c;那么 int b a; 这条代码就带有副作用 带有副作用的宏参数 代码演示&#xff1a…