• 第8章 Spring(一)


    8.1 Spring是什么?为什么要用它

    难度:★★★★

    重点:★★★★

    白话解析

    Spring目前是Java技术体系中最核心的框架,没有之一,不管是SpringBoot也好还是SpringCloud,都是建立在Spring的基础之上的(这句话别不当回事,后面讲SpringBoot和SpringCloud的时候,你们就会真正理解Spring的重要性)。

    概念:它其实就是一个轻量级的应用框架。

    作用:最最核心功能就是帮程序员管理Bean对象的(IoC)。面向切面编程(AOP)。

    1、IOC:

    举个最简单的例子来感受一下它的核心功能:如果没有Spring的话,我们开发的时候都需要自己去创建Bean对象,就比如在Controller层会调用某些Service,那这个时候我们需要通过new关键字创建大量的Service对象,如果换一个Controller类的话,我们又得重新创建(一般情况下是这样的),这极大的增加了我们程序员的工作量,对象之间的耦合性还高,同时还不方便做扩展。

    自从有了Spring之后,程序员不需要自己去创建一些核心对象了,只需要在类上面加一些注解,例如@Controller、@Service或者@Component等,Spring自动会帮我们创建对象,然后将这些对象存在一个全局的缓存里面,在当前项目的任何地方,都可以通过缓存去拿到它。这就减少了程序员的工作量了。

    同时Spring在帮我们创建对象的整个流程中,还给我们提供了各种接口,这些接口都是用来做扩展或者功能增强的。只需要你的类实现这些接口并重写相应的方法,那当你的类被实例化的时候,Spring就会去执行你重写的方法,这就是扩展。

    2、AOP:

    就是在执行真正的业务代码之前或者之后,先做一下功能增强,执行一下别的功能,比如打印日志啊,系统监控啊,流量统计啊、事务管理啊等等。说到功能增强立马就要想到代理,没错,AOP的核心就是代理了,然后代理对象搞定之后,还要实现一下拦截点,拦截之后,你可以去做一些你想要的功能,说的形象一点AOP就好比一把刀把所有的请求全部切断,让他们全部暂停执行,先来执行我定义的逻辑。

    参考答案

    1、spring是一个开源的轻量级JavaBean容器框架。

    2、作用:

    • 帮程序员管理Bean对象,减轻工作量

    • 能够降低对象与对象之间的耦合性

    • 提供多种扩展接口,增加系统的鲁棒性

    • 能够将系统功能和业务功能开发分开,同时现在市面上Java技术都能很好的集成Spring,让开发变得简单灵活

    (作用说了一大堆,其实不用背,关键是要自己能理解)

    8.2 Spring包括哪些核心模块

    难度:★★★

    重点:★★

    白话解析

    Spring的整体架构实际上是比较庞大的,对于初级程序员而言,只要理解几个比较重要的模块就好了。

    1、Web:提供一些集成的特性,主要为处理前端请求提供支持。

    2、Data Access/Integration:跟数据库打交道的:

    • JDBC:封装那堆JDBC代码的。

    • ORM:提供标准,然后让Mybatis或者Hibernate这些框架集成的。

    • Transactions:Spring统一管理事务的,支持编程和声明式事务管理。

    3、AOP:提供了面向切面编程实现。

    4、Aspects:提供与 AspectJ 的集成,是一个功能强大且成熟的面向切面编程(AOP)框架。

    5、Core Container(Spring 的核心容器)

    • Beans 模块:提供了框架的基础部分,包括控制反转(IoC)和依赖注入(DI)。

    • Core 核心模块:封装了 Spring 框架的底层部分,包括资源访问、类型转换及一些常用工具类。

    • Context 上下文模块:建立在 Core 和 Beans 模块的基础之上。

    5、Test:为测试提供支持的。

    参考答案

    1、Web模块

    2、JDBC模块

    3、AOP模块

    4、Aspects模块

    5、Beans、Core、Context模块

    6、Test模块。

    8.3 Spring中用到哪些设计模式

    难度:★★★

    重点:★★

    白话解析

    搞明白Spring的概念和组成架构之后,接下来就是明确它在设计上的艺术性了,Spring的作者Rod Johnson不仅是搞技术的,这哥们还是个搞音乐的,他获得过音乐博士学位,所以他创造Spring的时候也带了艺术性的。设计模式这块我们先记住,后面在中级篇的时候还会系统讲的。Spring中的设计模式比较多,不需要都记住,简单的理解加黑的那几个就好了。

    1、简单工厂模式:IoC容器中的BeanFactory就是一个简单工厂,用来创建对象的。

    2、工厂方法模式:FactoryBean就是典型的工厂方法模式。

    3、单例模式:Bean默认为单例模式。

    4、原型模式:Bean可以手动设置成prototype,表示每次拿到的都是不同的bean对象。

    5、代理模式:这种模式就是用来做功能增强的,比如在执行真正的业务逻辑之前先打印日志啊,执行完业务逻辑之后再统计啊等等,AOP用到了JDK的动态代理和CGLIB字节码生成技术。

    6、模板方法:用来解决代码重复的问题。比如把JDBC的那几行重复代码抽象提出来。

    7、观察者模式:比如监听器:ApplicationListener,它会观察监听某些事件,一旦发生了某些事件,ApplicationListener的实现类就会被调用。

    8、策略模式:定义一系列算法,将每一个算法封装起来,并让它们可以相互替换。

    9、适配器模式:作为两个不兼容的接口之间的桥梁,实际上相当于中介。

    10、装饰器模式:动态给一些对象增加额外的功能。

    11、建造者模式:拿到一个简单对象,然后把简单对象一步步建造成具有复杂功能的对象。

    12、责任链模式:比如WebFilterChain,就是把一次请求要执行的逻辑封装成一条链路,一步步执行。

    参考答案

    1、简答工厂、工厂方法模式

    2、单例模式

    3、代理模式

    4、模板方法模式

    5、观察者模式

    6、装饰器模式

    8.4 如何理解IoC

    难度:★★

    重点:★★★★

    白话解析

    IoC可以说是Spring框架中最重要的内容之一了,它贯穿整个Spring的生命周期;今后学习到任何要集成进Spring的技术组件,几乎都离不开IoC。

    参考答案

    1、IoC是什么:IoC是Inversion of Control的简写,也叫控制反转;Spring出现以前是由程序员来控制创建对象的,Spring出现以后,程序员把创建对象的权利交给了IoC容器,控制权反转了。

    而IoC容器说白了就是一些Map啊、List啊甚至一些对象等,用来缓存Bean对象、参数什么的。例如BeanFactory啊、ApplicationContext啊都可以理解成IoC容器。

    2、IoC工作大致流程:

    • 程序员通过 XML 配置文件、注解(@Component)、Java 配置类(@Bean)等方式,对 Java 对象进行定义。

    • Spring 启动时,IoC 容器会自动根据对象定义,将这些对象创建并缓存到IoC容器中。

    • 当我们想要使用某个 Bean 时,可以直接从 IoC 容器中获取(例如通过 ApplicationContext 的 getBean() 方法),而不需要手动通过代码(例如 new Obejct() 的方式)创建。

    8.5 讲讲BeanFactory和FactoryBean的区别

    难度:★

    重点:★★★

    白话解析

    这道题其实没什么难度,关键是两个单词顺序换来换去,容易混淆。

    参考答案

    1、BeanFactory是Bean工厂,而FactoryBean是一个Bean接口。

    2、BeanFactory是一个IoC容器,实际上是所有IoC容器中管理对象容器的顶级接口;它其实作为一个Bean工厂,提供了一套统一的创建、存储、管理、获取Bean对象的流水线一样的规范方法(当然实现是由它的子类完成)。 BeanFactory 在产生 Bean 的同时,还提供了解决 Bean 之间的依赖注入的能力,也就是所谓的 DI。

    FactoryBean实际上就是让我们在流水线生产Bean对象之外,还可以自定义一个Bean并且加载到 IOC 容器里面。它里面有一个重要的方法叫 getObject(),这个方法里面就是用来实现动态构建 Bean的过程。如果你想做一些羞羞的定制,你就可以让你的类实现FactoryBean接口,然后重写getObject方法。

    总结起来就一句话,BeanFactory是做流水线工作的,FactoryBean是做私人订制的。

    8.6 讲讲BeanFactory和ApplicationContext的区别

    难度:★

    重点:★★

    白话解析

    这两个都是Spring中的容器,只不过BeanFactory是顶级的,而ApplicationContext是BeanFactory的子接口。从这一层去理解,ApplicationContext肯定具备了BeanFactory的所有功能,同时还提供了一些属于自己的附加功能。

    参考答案

    1、他们两都是Spring的核心容器接口,BeanFactory是顶级的,ApplicationContext是BeanFactory的子接口。

    2、BeanFactory提供了对Bean的创建、存储、管理、获取等一系列规范化的方法;ApplicationContext在具备这些方法之外,它还继承了EnvironmentCapable、MessageSource等接口(这里就不写了,反正不需要去记),这样使得它拥有了更完善的功能,例如支持国际化、统一资源文件访问方式、加载多配置文件、载入多个上下文等其他功能。

    8.7 如何理解DI

    难度:★★

    重点:★★★★

    白话解析

    前面已经介绍了IoC,它就是控制反转,它的实现方式主要有两种:依赖注入(DI)和依赖查找(DL)。

    先给一段代码:

    1. public class Girl{
    2. Boy boy;
    3. }

    依赖查找:Girl对象依赖Boy,当它实例化的时候,Girl会通过容器的 API 来查找Boy对象;需要手动去查找。

    依赖注入:Girl和Boy对象统一由容器进行管理,由IoC Service Provider 来自动完成依赖关系的绑定。当Girl要依赖Boy的时候,IoC Service Provider会从容器中拿到相应的Boy对象,并通过Girl的构造方法或者set方法把Boy对象设置进Girl。

    参考答案

    Denpendency Injection的简写,也叫依赖注入。在IoC容器创建对象的时候进行属性注入的。

    8.8 Spring常用的依赖注入方式有哪些

    难度:★★

    重点:★★

    白话解析

    理解了IoC和DI的概念之后,接下来要搞明白依赖注入属性的使用方式了。现在XML方式已经属于淘汰行列了,所以不再介绍XML方式的依赖注入了,只讲基于注解的方式。

    注解方式注入有三个注解:

    1、@Value:注入普通属性的,例如配置文件application.properties文件中配置的属性,就能通过@Value注入。

    2、@Resource:Java原生注解,用来注入对象类型的,默认按照名称进行注入。

    3、@Autowired:Spring框架提供的注解,也是用来注入对象类型,默认按照类型注入。

    如果一个接口有两个或者多个实现类,此时通过Autowired进行注入的时候会报错,此时我们可以通过@Qualifier来解决,例如:

    1. @Configuration
    2. public class ConfigurationDemo{
    3. @Bean("demo01")
    4. public ServiceDmeo serviceDmeo01(){
    5. return new ServiceDmeo();
    6. }
    7. @Bean("demo02")
    8. public ServiceDmeo serviceDmeo02(){
    9. return new ServiceDmeo();
    10. }
    11. }
    12. public class UseDemo{
    13. @Autowired
    14. @Qualifier("demo01")
    15. private ServiceDmeo serviceDemo;
    16. }

    它可以对类的成员属性,方法和构造方法进行修饰。

    • 构造器注入

    1. @Service
    2. public class Girl{
    3. private Boy boy;
    4. @Autowired
    5. public Girl(Boy boy){
    6. this.boy = boy;
    7. }
    8. }
    • 普通方法注入
    1. @Service
    2. public class Girl {
    3. @Autowired
    4. public void test(Boy boy){
    5. System.out.println(boy);
    6. }
    7. }
    8. @Service
    9. public class Girl {
    10. private Boy boy;
    11. @Autowired
    12. public void setBoy(Boy boy){
    13. this.boy = boy;
    14. }
    15. }
    • 属性注入
    1. @Service
    2. public class Girl{
    3. @Autowired
    4. private Boy boy;
    5. }

    参考答案

    1、构造器注入

    2、普通方法注入

    3、属性注入

    8.9 如何理解循环依赖?怎么解决它呢

    难度:★★★★

    重点:★★★

    白话解析

    这道题能理解死循环的形成和如何打破就能回答出来。

    想必依赖注入的概念大家都已经明确了,那在依赖注入的时候会存在一种死循环的概念,我们通过代码看看:

    1. public class Girl{
    2. @Autowired
    3. private Boy boy;
    4. }
    5. public class Boy{
    6. @Autowired
    7. private Girl girl;
    8. }

    这个时候你中有我,我中有你,那在初始化Girl的时候,会进行属性注入,但是此时Boy如果还没初始化好呢,那这个时候Spring又去初始化Boy,但是Boy也需要属性注入Girl,但是Girl也没有初始化好啊,完犊子了,死循环了。

    Spring肯定考虑到这个问题了,所以提出了通过三级缓存的概念来解决它。

    1、先明确三级缓存的概念:

    • 一级缓存:用来存完整的Bean对象。

    • 二级缓存:存已经实例化,但是还没有初始化的Bean对象。

    • 三级缓存:用来存Bean工厂对象,这个工厂对象的功能就是生产Bean对象的并存到二级缓存中。

    2、然后再来通过图解释三级缓存解决循环依赖的流程

    参考答案

    概念:循环依赖的意思就是Girl中有Boy,Boy中有Girl,他们相互依赖,在实例化之后进行属性注入的时候会造成死循环。

    解决方案:通过三级缓存去解决。核心思想就是用一个替代的Girl工厂对象先存到三级缓存里面去,然后Boy在属性注入的时候就能找到Girl的这个工厂,然后通过工厂创建一个不成熟的Girl作为一个替代先进行注入,然后就把这个死循环打破了。

    8.10 Spring循环依赖不用二级或者三级缓存可以吗

    难度:★★★

    重点:★★★

    白话解析

    1、二级缓存:

    从上面那道题我们理解了循环依赖的概念,但是你们有没有觉得二级缓存有点多余啊,从图上看到,其实二级缓存没起到什么实质性的作用,那把它干掉可不可以呢?

    答案肯定是不可以的。我这里举个例子,假设现在Girl同时依赖了Boy和Man,然后Boy和Man也依赖了Girl。

    2、三级缓存

    那又有问题了,可以不可以不要三级缓存,直接在二级缓存里面创建不成熟的Girl,让Boy和Man直接去二级缓存里面拿就好了。

    我觉得如果你不用代理做增强的话,理论上是可以的。但是要用代理的话,必须要用三级缓存;

    因为在工厂创建对象的时候能给我们创建代理(AbstractAutowireCapableBeanFactory#doCreateBean方法中)。

    参考答案

    1、二级缓存必须要有,如果没有二级缓存,当Girl类依赖注入多个其他类的,且其他类也都依赖Girl的时候,会出现注入的不是同一个Girl的情况。

    2、三级缓存:需要用代理的时候必须要有,如果不用代理可以不需要。

  • 相关阅读:
    【FFMPEG】解决截取MP4视频的中间段时,截取完成后前几帧视频卡住,但是有声音的情况
    一、摘要和简介
    Ubuntu安装截图工具Shutter及使用
    主流的深度学习推理架构有哪些呢?
    C++-逆向分析-IDA-IDC脚本-修改指定地址的函数名-函数重命名
    .Net Core 获取文件编码格式
    深度学习常见网络及报错大汇总:vgg训练 tensorflow版本匹配 模型保存与加载 loss特别大
    机器学习中的无监督学习是什么?
    es的使用方法以及概念
    C++——电话号码的字母组合问题
  • 原文地址:https://blog.csdn.net/Eclipse_2019/article/details/133382510