当前位置: 首页 > web >正文

Java_day30-35

Java_简答

  • day 30
    • 1 volatile 关键字的作用有那些?
    • 2volatile 与synchronized 的对比
    • 3JDK8有哪些新特性
  • day 31
    • 1为什么要有线程池?
    • 2说一说线程池有哪些常用参数
    • 3BIO、NIO、AIO 的区别
  • day 32
    • 1Java 内存区域有哪些部分
    • 2介绍一下什么是强引用、软引用、弱引用、虚引用
    • 3有哪些垃圾回收算法
    • 4有哪些垃圾回收器
  • day 33
    • 1类加载机制介绍一下
    • 2介绍一下双亲委派机制
    • 3说一说你对Spring AOP的了解
    • 4说一说你对 Spring中IOC的理解
  • day 34
    • 1Bean的作用域
    • 2Bean的生命周期
    • 3Spring循环依赖是怎么解决的
    • 4Spring 中用到了那些设计模式
  • day 35
    • 1描述一下SpringMVC的执行流程
    • 2SpringBoot Starter有什么用
    • 3SpringBoot的常用注解


day 30

1 volatile 关键字的作用有那些?

volatile 通常被比喻成"轻量级的 synchronized ",它不需要获取和释放锁,是Java并发编程中比较重要的一个关键字。 和 synchronized 不同, volatile 是一个变量修饰符,只能用来修饰变量。无法修饰方法及代码块等。

volatile关键字在Java中主要用于保证变量的内存可见性和禁止指令重排。

保证可见性: 确保当一个线程修改了一个volatile变量时,其他线程能够立即看到这个改变。
当对非 volatile 变量进行读写的时候,每个线程先从主内存拷贝变量到 CPU 缓存中,如果计算机有多个 CPU,每个线程可能在不同的 CPU 上 被处理,这意味着每个线程可以拷贝到不同的 CPU cache 中。
volatile 变量不会被缓存在寄存器或者对其他处理器不可见的地方,保证了每次读写变量都从主内存中读,跳过 CPU cache 这一步。当一个线程修改了这个变量的值,新值对于其他线程是立即得知的。
禁止指令重排: volatile变量的写操作在JVM执行时不会发生指令重排,确保写入操作在读取操作之前完成。
指令重排序是 JVM 为了优化指令、提高程序运行效率,在不影响单线程程序执行结果的前提下,尽可能地提高并行度, 包括编译器重排序和运行时重排序;
volatile 变量禁止指令重排序。针对 volatile 修饰的变量,在读写操作指令前后会插入内存屏障,指令重排序时不能把后面的指令重排序到内存屏障.
虽然volatile可以确保可见性,但它不保证复合操作的原子性。

2volatile 与synchronized 的对比

volatile和synchronized都是Java中用于多线程同步的工具,在用途、原子性、互斥性、性能和使用场景上有一定的区别。

机制和用途
synchronized:用于提供线程间的同步机制。当一个线程进入一个由 synchronized 修饰的代码块或方法时,它会获取一个监视器锁,这保证了同一时间只有一个线程可以执行这段代码。其主要用途是确保数据的一致性和线程安全性。
volatile:用于修饰变量。volatile 的主要作用是确保变量的可见性,即当一个线程修改了一个 volatile 变量的值,其他线程能够立即看到这个修改。此外,它还可以防止指令重排序。但是,volatile 并不能保证复合操作的原子性。
总结: volatile 关键字主要用于解决变量在多个线程之间的可见性,而 synchronized 关键字解决的是多个线程之间访问资源的同步性。
原子性
synchronized:可以保证被其修饰的代码块的原子性,即这段代码在执行过程中不会被其他线程打断。
volatile:只能保证单个读写操作的原子性,对于复合操作(如自增、自减等)则无法保证原子性。
性能
volatile 通常比 synchronized 更轻量级,所以 volatile 性能肯定比 synchronized 关键字要好; 因为它不涉及锁的获取和释放。但是,这也意味着它提供的同步级别较低。

互斥性:
synchronized:提供了互斥性,即同一时间只有一个线程可以执行被其修饰的代码块或方法。
volatile:不提供互斥性,只是确保变量的可见性。
使用场景
volatile适用于简单的内存可见性要求
而synchronized可以通过ReentrantLock等扩展为更灵活的锁机制,适用于需要保证原子性、可见性和互斥的复杂同步场景。

3JDK8有哪些新特性

Lambda 表达式:允许以更简洁的语法编写匿名函数。
Stream API: Stream API 提供了一种声明式的方式来对集合进行操作。它支持各种操作,如过滤、映射、排序、归约等。
函数式接口:Java 8 提供了一系列函数式接口,如 Consumer、Predicate、Function 等。
新的日期和时间 API: Java 8 引入了 java.time 包,提供了全新的日期和时间 API。它解决了旧的 java.util.Date 和 java.util.Calendar 的诸多问题,并提供了更加清晰和易用的日期和时间处理方式。
方法引用:方法引用允许通过方法的名称来引用一个方法,而不是执行它。它们提供了一种更简洁的方式来传递方法作为参数,如 System.out::println。

day 31

1为什么要有线程池?

资源管理: 在多线程应用中,每个线程都需要占用内存和CPU资源,如果不加限制地创建线程,会导致系统资源耗尽,可能引发系统崩溃。线程池通过限制并控制线程的数量,帮助避免这个问题。
提高性能:通过重用已存在的线程,线程池可以减少创建和销毁线程的开销。
任务排队:线程池通过任务队列和工作线程的配合,合理分配任务,确保任务按照一定的顺序执行,避免线程竞争和冲突
统一管理:线程池提供了统一的线程管理方式,可以对线程进行监控、调度和管理。
总结:采用多线程编程的时候如果线程过多会造成系统资源的大量占用,降低系统效率。如果有些线程存活的时间很短但是又不得不创建很多这种线程也会造成资源的浪费。线程池的作用就是创造并且管理一部分线程,当系统需要处理任务时直接将任务添加到线程池的任务队列中,由线程池决定由哪个空闲且存活线程来处理,当线程池中线程不够时会适当创建一部分线程,线程冗余时会销毁一部分线程。这样提高线程的利用率,降低系统资源的消耗。

2说一说线程池有哪些常用参数

corePoolSize核心线程数:线程池中长期存活的线程数。
maximumPoolSize最大线程数:线程池允许创建的最大线程数量,当线程池的任务队列满了之后,可以创建的最大线程数。
keepAliveTime空闲线程存活时间:当线程数大于corePoolSize时,多余的空闲线程能等待新任务的最长时间。
TimeUnit: 与keepAliveTime一起使用,指定keepAliveTime的时间单位,如秒、分钟等。
workQueue线程池任务队列: 线程池存放任务的队列,用来存储线程池的所有待执行任务。
ThreadFactory:创建线程的工厂: 线程池创建线程时调用的工厂方法,通过此方法可以设置线程的优先级、线程命名规则以及线程类型(用户线程还是守护线程)等。
RejectedExecutionHandler拒绝策略: 当线程池的任务超出线程池队列可以存储的最大值之后,执行的策略。

3BIO、NIO、AIO 的区别

BIO、AIO和NIO是Java中不同的I/O模型,它们在处理输入输出操作时有不同的特点。

BIO: 阻塞式的I/O模型。当一个线程执行I/O操作时,如果数据还没准备好,这个线程会被阻塞,直到数据到达。适合连接数较少且固定的场景,但扩展性较差。
NIO: 非阻塞的I/O模型。NIO使用缓冲区和通道来处理数据,提高了I/O操作的效率。支持面向缓冲区的读写操作,可以处理大量并发的连接。
AIO: 异步I/O模型,从Java 7开始引入。在AIO中,I/O操作被发起后,线程可以继续执行其他任务,一旦I/O操作完成,操作系统会通知线程。适合需要处理大量并发I/O操作,且希望避免I/O操作阻塞线程的场景。
使用场景:
BIO适合低并发、连接数较少的应用。
NIO适合高并发、需要处理大量连接的应用。
AIO适合需要高性能、异步处理I/O操作的场景。

day 32

1Java 内存区域有哪些部分

Java的内存区域主要分为以下几个部分:

程序计数器:程序计数器是一块较小的内存空间,可以看作是当前线程所执行的字节码的行号指示器。在多线程环境下,每个线程都有自己独立的程序计数器。当线程执行Java方法时,程序计数器记录的是正在执行的虚拟机字节码指令的地址。
Java虚拟机栈:每个Java线程都有一个私有的Java虚拟机栈,与线程同时创建。每个方法在执行时都会创建一个栈帧,用于存储局部变量、操作数栈、动态链接、方法出口等信息。栈帧在方法调用时入栈,方法返回时出栈。
本地方法栈: 本地方法栈与Java虚拟机栈类似,但它为本地方法服务。本地方法是用其他编程语言(如C/C++)编写的,通过JNI与Java代码进行交互。
堆:Java堆是Java虚拟机中最大的一块内存区域,用于存储对象实例。所有的对象实例和数组都在堆上分配内存。堆是被所有线程共享的一块内存区域,在虚拟机启动时创建。堆可以分为新生代和老年代等不同的区域,其中新生代又包括Eden空间、Survivor空间(From和To)。
方法区: 方法区用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。在HotSpot虚拟机中,方法区也被称为永久代,但在较新的JVM版本中,永久代被元空间所取代。
运行时常量池:是方法区的一部分,用于存储编译期生成的类、方法和常量等信息。
字符串常量池: 字符串常量池 是 JVM 为了提升性能和减少内存消耗针对字符串专门开辟的一块区域,主要目的是为了避免字符串的重复创建。
直接内存:不是Java虚拟机运行时数据区的一部分,但Java可以通过NIO操作直接内存,提高IO性能。

2介绍一下什么是强引用、软引用、弱引用、虚引用

这四种引用决定了对象的生命周期以及垃圾收集器如何收集垃圾。

强引用:最常见的引用类型。如果一个对象具有强引用,那么垃圾收集器绝不会回收它。
软引用:软引用用于描述一些还有用但非必需的对象。如果一个对象只有软引用指向它,那么在系统内存不足时,垃圾回收器会尝试回收这些对象。软引用通常用于实现内存敏感的缓存,可以在内存不足时释放缓存中的对象。
弱引用:弱引用比软引用的生命周期更短暂。如果一个对象只有弱引用指向它,在进行下一次垃圾回收时,不论系统内存是否充足,这些对象都会被回收。弱引用通常用于实现对象缓存,但不希望缓存的对象影响垃圾回收的情况。
虚引用:虚引用是Java中最弱的引用类型。如果一个对象只有虚引用指向它,那么无论何时都可能被垃圾回收器回收,但在对象被回收之前,虚引用会被放入一个队列中,供程序员进行处理。虚引用主要用于跟踪对象被垃圾回收的时机,进行一些必要的清理或记录。

3有哪些垃圾回收算法

标记-清除算法
标记清除算法将垃圾回收分为两个阶段:标记阶段和清除阶段。 在标记阶段首先通过根节点(GC Roots),标记所有从根节点开始的对象,未被标记的对象就是未被引 用的垃圾对象。然后,在清除阶段,清除所有未被标记的对象。 适用场合:

存活对象较多的情况下比较高效

适用于年老代(即旧生代)

复制算法
从根集合节点进行扫描,标记出所有的存活对象,并将这些存活的对象复制到一块儿新的内存上去,之后将原来的那一块儿内存全部回收掉 现在的商业虚拟机都采用这种收集算法来回收新生代。 适用场合:

存活对象较少的情况下比较高效

扫描了整个空间一次(标记存活对象并复制移动)

适用于年轻代(即新生代):基本上98%的对象是”朝生夕死”的,存活下来的会很少

缺点:

需要一块儿空的内存空间

需要复制移动对象

复制算法的高效性是建立在存活对象少、垃圾对象多的前提下的。这种情况在新生代经常发生,但是在老年代更常见的情况是大部分对象都是存活对象。如果依然使用复制算法,由于存活的对象较多,复制的成本也将很高。

标记整理
标记-压缩算法是一种老年代的回收算法,它在标记-清除算法的基础上做了一些优化。 首先也需要从根节点开始对所有可达对象做一次标记,但之后,它并不简单地清理未标记的对象,而是将所有的存活对象压缩到内存的一端。之后,清理边界外所有的空间。这种方法既避免了碎片的产生,又不需要两块相同的内存空间,因此,其性价比比较高。

分代收集算法
分代收集算法就是目前虚拟机使用的回收算法,它解决了标记整理不适用于新年代的问题,将内存分 为各个年代。一般情况下将堆区划分为老年代(Tenured Generation)和新生代(Young Generation),在堆区之外还有一个代就是永久代(Permanet Generation)。 在不同年代使用不同的算法,从而使用最合适的算法,新生代存活率低,可以使用复制算法。而老年代对象存活率搞,没有额外空间对它进行分配担保,所以只能使用标记清除或者标记整理算法。

4有哪些垃圾回收器

新生代垃圾收集器
Serial 收集器(复制算法)是新生代单线程收集器,优点是简单高效,算是最基本、发展历史最悠久的收集器。它在进 行垃圾收集时,必须暂停其他所有的工作线程,直到它收集完成。
ParNew 收集器(复制算法)是新生代并行收集器,其实就是 Serial 收集器的多线程版本。
Parallel Scavenge 收集器是新生代并行收集器,追求高吞吐量,高效利用 CPU。

老年代垃圾收集器
Serial Old是Serial收集器的老年代版本,它同样是一个单线程(串行)收集器,使用标记整理算法。这个收 集器的主要意义也是在于给Client模式下的虚拟机使用。

Parallel Old 是Parallel Scavenge收集器的老年代版本,使用多线程和“标记-整理”算法。这个收集器在 1.6中才开始提供。

CMS 收集器是一种以获取最短回收停顿时间为目标的收集器。目前很大一部分的Java应用集中在互联网站或者B/S系统的服务端上,这类应用尤其重视服务器的响应速 度,希望系统停顿时间最短,以给用户带来较好的体验。CMS收集器就非常符合这类应用的需求

**CMS收集器是基于“标记-清除”算法实现的,**它的运作过程相对前面几种收集器来说更复杂一些,整个过 程分为4个步骤:

初始标记
并发标记
重新标记
并发清除
新生代和老年代垃圾收集器
G1收集器-标记整理算法 :JDK1.7后全新的回收器, 用于取代CMS收集器。

G1 收集器的优势:

独特的分代垃圾回收器,分代GC: 分代收集器, 同时兼顾年轻代和老年代
使用分区算法, 不要求eden, 年轻代或老年代的空间都连续
并行性: 回收期间, 可由多个线程同时工作, 有效利用多核cpu资源
空间整理: 回收过程中, 会进行适当对象移动, 减少空间碎片
可预⻅性: G1可选取部分区域进行回收, 可以缩小回收范围, 减少全局停顿

G1收集器的阶段分以下几个步骤:

初始标记(它标记了从GC Root开始直接可达的对象)
并发标记(从GC Roots开始对堆中对象进行可达性分析,找出存活对象)
最终标记(标记那些在并发标记阶段发生变化的对象,将被回收)
筛选回收(首先对各个Regin的回收价值和成本进行排序,根据用户所期待的GC停顿时间指定回收计 划,回收一部分Region)

day 33

1类加载机制介绍一下

类加载机制是Java虚拟机运行Java程序时负责将类加载到内存中的过程。它包括以下几个步骤:

加载: 在此阶段,类加载器负责查找类的字节码文件,并将其加载到内存中。字节码可以来自文件系统、网络等位置。加载阶段不会执行类中的静态初始化代码。

连接:连接阶段包括三个子阶段:

验证:确保加载的类文件格式正确,并且不包含不安全的构造。
准备:在内存中为类的静态变量分配内存空间,并设置默认初始值。这些变量在此阶段被初始化为默认值,比如数值类型为0,引用类型为null。
解析:将类、接口、字段和方法的符号引用解析为直接引用,即内存地址。这一步骤可能包括将常量池中的符号引用解析为直接引用。
初始化:在此阶段,执行类的静态初始化代码,包括静态字段的赋值和静态代码块的执行。静态初始化在类的首次使用时进行,可以是创建实例、访问静态字段或调用静态方法。

2介绍一下双亲委派机制

双亲委派机制是Java类加载器中的一种设计模式,用于确定类的加载方式和顺序。这个机制确保了**Java核心库的安全性和一致性。**该机制的核心思想是:如果一个类加载器收到了类加载请求,默认先将该请求委托给其父类加载器处理。只有当父级加载器无法加载该类时,才会尝试自行加载。

双亲委派机制能够提高安全性,防止核心库的类被篡改。因为所有的类最终都会通过顶层的启动类加载器进行加载。另外由于类加载器直接从父类加载器那里加载类,也避免了类的重复加载。

3说一说你对Spring AOP的了解

面向切面编程,可以说是面向对象编程的补充和完善。OOP 引入封装、继承、多态等概念来建立一种对象层次结构。不过 OOP 允许开发者定义纵向的关系,但并不适合定义横向的 关系,例如日志功能。 AOP 技术恰恰相反,它利用一种称为"横切"的技术,剖解开封装的对象内部,并将那些影响了多个类的 公共行为封装到一个可重用模块,并将其命名为切面。所谓"切面",简单说就是那些与业务无关,却为业务模块所共同调用的逻辑或责任封装起来,便于减少系统的重复代码,降低模块之间的 耦合度,并有利于未来的可操作性和可维护性。

Spring 中 AOP 代理由 Spring 的 IOC 容器负责生成、管理,其依赖关系也由 IOC 容器负责管理。因此, AOP 代

理可以直接使用容器中的其它 bean 实例作为目标,这种关系可由 IOC 容器的依赖注入提供。Spring 创建代理的规则为:

默认使用 JDK 动态代理来创建AOP代理,这样就可以为任何接口实例创建代理了

当需要代理类,而不是代理接口的时候,Spring 会切换为使用 CGLIB代理 ,也可强制使用 CGLIB

AOP 编程其实是很简单的事情,纵观 AOP 编程,程序员只需要参与三个部分:

定义普通业务组件
定义切入点,一个切入点可能横切多个业务组件
定义增强处理,增强处理就是在 AOP 框架为普通业务组件织入的处理动作
所以进行 AOP 编程的关键就是定义切入点和定义增强处理,一旦定义了合适的切入点和增强处理,AOP 框架将自动生成 AOP 代理,即: 代理对象的方法=增强处理+被代理对象的方法。

4说一说你对 Spring中IOC的理解

什么是 IOC
Spring的IOC,也就是控制反转,它的核心思想是让对象的创建和依赖关系由容器来控制,不是我们自己new出来的,这样各个组件之间就能保持松散的耦合。

这里的容器实际上就是个Map, Map 中存放的是各种对象。通过DI依赖注入,Spring容器可以在运行时动态地将依赖注入到需要它们的对象中,而不是对象自己去寻找或创建依赖。这样可以很大程度上简化应用的开发,把应用从复杂的依赖关系中解放出来。举例来说,在实际项目中一个 Service 类可能有几百甚至上千个类作为它的底层,假如我们需要实例化这个 Service,你可能要每次都要搞清这个 Service 所有底层类的构造函数,如果利用 IoC 的话,你只需要配置好,然后在需要的地方引用就行了。

如何配置
Spring 时代我们一般通过 XML 文件来配置,后来开发人员觉得 XML 文件来配置不太好,于是 SpringBoot 注解配置就慢慢开始流行起来。使用配置可以告诉Spring容器如何创建对象、如何管理对象的生命周期。

总结来说,Spring的IOC容器是一个中央化的、负责管理应用中所有对象生命周期的强大工具

day 34

1Bean的作用域

在 Spring 中,那些组成应用程序的主体及由 Spring IOC 容器所管理的对象,被称之为 Bean。而 Bean 的作用域定义了在应用程序中创建的 Bean 实例的生命周期和可见范围,主要有以下几种。

单例:这是默认的作用域,当一个 Bean 的作用域为 Singleton,那么 Spring IoC 容器中只会存在一个共享的 Bean 实例,并且所有对 Bean 的请求,只要 id 与该 bean 定义相匹配,则只会返回 bean 的同一实例。
原型:当一个 bean 的作用域为 prototype,表示一个 bean 定义对应多个对象实例。prototype 作用域的 bean 会导致在每次对该 bean 请求时都会创建一个新的 bean 实例。因此,每次请求都会得到一个新的 Bean 实例。
请求:一个HTTP请求对应一个Bean实例,每个请求都有自己的Bean实例,且该Bean仅在请求期间有效。
会话:一个HTTP会话对应一个Bean实例,Bean的生命周期与用户的会话周期相同。
应用程序:对于定义在ServletContext中的Bean,整个Web应用程序共享一个Bean实例。
Websocket: WebSocket生命周期内,每个WebSocket会话拥有一个Bean实例。

2Bean的生命周期

Spring Bean的生命周期,其实就是Spring容器从创建Bean到销毁Bean的整个过程。这里面有几个关键步骤:

实例化Bean: Spring容器通过构造器或工厂方法创建Bean实例。
设置属性:容器会注入Bean的属性,这些属性可能是其他Bean的引用,也可能是简单的配置值。
检查Aware接口并设置相关依赖:如果Bean实现了BeanNameAware或BeanFactoryAware接口,容器会调用相应的setBeanName或setBeanFactory方法。
BeanPostProcessor:在Bean的属性设置之后,Spring会调用所有注册的BeanPostProcessor的postProcessBeforeInitialization方法。
初始化Bean: 如果Bean实现了InitializingBean接口,容器会调用其afterPropertiesSet方法。同时,如果Bean定义了init-method,容器也会调用这个方法。
BeanPostProcessor的第二次调用**:容器会再次调用所有注册的BeanPostProcessor的postProcessAfterInitialization方法,这次是在Bean初始化之后。
使用Bean:此时,Bean已经准备好了,可以被应用程序使用了。
处理DisposableBean和destroy-method:当容器关闭时,如果Bean实现了DisposableBean接口,容器会调用其destroy方法。如果Bean定义了destroy-method,容器也会调用这个方法。
Bean销毁:最后,Bean被Spring容器销毁,结束了它的生命周期。

3Spring循环依赖是怎么解决的

什么是循环依赖
两个或者两个以上的 bean 互相持有对方,最终形成闭环。比如 Bean A 依赖于 Bean B,而 Bean B 又依赖于 Bean A,形成了一个循环依赖关系。这种情况下,如果不处理,会导致 Spring 容器无法完成 Bean 的初始化,从而抛出循环依赖异常。

怎么检测是否存在循环依赖
检测循环依赖相对比较容易,Bean在创建的时候可以给该Bean打标,如果递归调用回来发现正在创建中的话,即说明了循环依赖了。

如何解决
构造器循环依赖:Spring容器在创建Bean时,如果遇到循环依赖,通常是无法处理的,因为这会导致无限递归创建Bean实例。所以,构造器注入是不支持循环依赖的。
字段注入或Setter注入:使用了三级缓存来解决循环依赖问题。
首先,Spring容器会创建一个Bean的原始实例,但此时Bean的属性尚未设置,这个实例被存放在一级缓存中。
当Bean的属性被设置时,如果属性值是其他Bean的引用,Spring会去检查二级缓存,看是否已经有该Bean的引用存在。
如果二级缓存中没有,Spring会尝试创建这个被引用的Bean,并将其放入三级缓存。
最后,当Bean的属性设置完成后,原始的Bean实例会被放入二级缓存,供其他Bean引用
使用@Lazy注解:通过@Lazy注解,可以延迟Bean的加载,直到它被实际使用时才创建,这可以避免一些循环依赖的问题。

4Spring 中用到了那些设计模式

工厂设计模式 : Spring 使用工厂模式通过 BeanFactory、ApplicationContext 创建 bean 对象。
代理设计模式 : Spring AOP 功能的实现。
单例设计模式 : Spring 中的 Bean 默认都是单例的。
模板方法模式 : Spring 中 jdbcTemplate、hibernateTemplate 等以 Template 结尾的对数据库操 作的类,它们就使用到了模板模式。
包装器设计模式 : 我们的项目需要连接多个数据库,而且不同的客户在每次访问中根据需要会去访 问不同的数据库。这种模式让我们可以根据客户的需求能够动态切换不同的数据源。
观察者模式: Spring 事件驱动模型就是观察者模式很经典的一个应用。
适配器模式 :Spring AOP 的增强或通知 (Advice) 使用到了适配器模式、Spring MVC 中也是用到了 适配器模式适配 Controller。

day 35

1描述一下SpringMVC的执行流程

用户发送请求至前端控制器 DispatcherServlet。
DispatcherServlet 收到请求调用 HandlerMapping 处理器映射器。
处理器映射器找到具体的处理器(可以根据 xml 配置、注解进行查找),生成处理器对象及处理器拦截 器(如果有则生成)一并返回给 DispatcherServlet。
DispatcherServlet 调用 HandlerAdapter 处理器适配器。
HandlerAdapter 经过适配调用具体的处理器(Controller,也叫后端控制器)。
Controller 执行完成返回 ModelAndView。
HandlerAdapter 将 controller 执行结果 ModelAndView 返回给 DispatcherServlet。
DispatcherServlet 将 ModelAndView 传给 ViewReslover 视图解析器。
ViewReslover 解析后返回具体 View。
DispatcherServlet 根据 View 进行渲染视图(即将模型数据填充至视图中)
DispatcherServlet响应用户。

2SpringBoot Starter有什么用

Spring Boot Starter 的作用是简化和加速项目的配置和依赖管理。

Spring Boot Starter 可以理解为一种预配置的模块,它封装了特定功能的依赖项和配置, ,开发者只需引入相关的 Starter 依赖,无需手动配置大量的参数和依赖项。常用的启动器包括 spring-boot-starter-web(用于Web应用)、spring-boot-starter-data-jpa(用于数据库访问)等。 引入这些启动器后,Spring Boot 会自动配置所需的组件和 Bean,无需开发者手动添加大量配置。
Starter还管理了相关功能的依赖项,包括其他Starter和第三方库,确保它们能够良好地协同工作,避免版本冲突和依赖问题。
Spring Boot Starter 的设计使得应用可以通过引入不同的Starter来实现模块化的开发。每个Starter都关注一个特定的功能领域,如数据库访问、消息队列、Web开发等。
开发者可以创建自定义的 Starter,以便在项目中共享和重用特定功能的配置和依赖项。

3SpringBoot的常用注解

@SpringBootApplication: 用于标识主应用程序类,通常位于项目的顶级包中。这个注解包含了 @Configuration、@EnableAutoConfiguration 和 @ComponentScan。
@Controller: 用于标识类作为 Spring MVC 的 Controller。
@RestController: 类似于 @Controller,但它是专门用于 RESTful Web 服务的。它包含了 @Controller 和 @ResponseBody。
@RequestMapping: 用于将HTTP请求映射到 Controller 的处理方法。可以用在类级别和方法级别。
@Autowired: 用于自动注入 Spring 容器中的 Bean,可以用在构造方法、字段、Setter 方法上。
@Service: 用于标识类作为服务层的 Bean。
@Repository: 用于标识类作为数据访问层的 Bean,通常用于与数据库交互。
@Component: 通用的组件注解,用于标识任何 Spring 托管的 Bean。
@Configuration: 用于定义配置类,类中可能包含一些 @Bean 注解用于定义 Bean。
@EnableAutoConfiguration: 用于启用 Spring Boot 的自动配置机制,根据项目的依赖和配置自动配置 Spring 应用程序。
@Value: 用于从属性文件或配置中读取值,将值注入到成员变量中。
@Qualifier:​ 与 @Autowired 一起使用,指定注入时使用的 Bean 名称。
@ConfigurationProperties: 用于将配置文件中的属性映射到 Java Bean。
@Profile: 用于定义不同环境下的配置,可以标识在类或方法上。
@Async: 用于将方法标记为异步执行。

http://www.xdnf.cn/news/1359.html

相关文章:

  • 5.2.3 WPF 中 XAML 文件 Converter 使用介绍
  • 私有知识库 Coco AI 实战(三):摄入 Elasticsearch 官方文档
  • 安装jdk报错2503、2502--右键msi文件没法管理员权限执行(Windows解决方案)
  • 栈和队列学习记录
  • 图聚类中的亲和力传播
  • 国产三维CAD皇冠CAD在机械及汽车零部件设计建模教程:斜滑动轴承
  • Python内置函数---bin()
  • 书籍推荐:《认知觉醒》一周岭
  • 单片机获取真实时间的实现方法
  • Windows 各版本查找计算机 IP 地址指南
  • 在Notepad++中使用NppAtyle插件格式化代码
  • 正则表达式的捕获组
  • 众趣科技X世界读书日丨数字孪生技术赋能图书馆空间智慧化运营
  • TCP四大特性面试回答引导
  • UniOcc:自动驾驶占用预测和预报的统一基准
  • 【华为】防火墙双击热备-之-主备模式-单外网线路
  • MYSQL-库的基本操作
  • 数据结构--AVL树
  • 【问题解决】本机navicat连接云服务器mysql
  • idea无法下载源代码
  • k8s 证书相关问题
  • Python 从PPT文档中提取图片和图片信息(坐标、宽度和高度等)
  • Linux 管道理解
  • 【计算机网络】现代网络技术核心架构与实战解析
  • OCR之身份证识别
  • MinIO 教程:从入门到Spring Boot集成
  • 极狐GitLab 的合并请求部件能干什么?
  • 数据结构-链表
  • OpenGL学习笔记(Blinn-Phong、伽马矫正、阴影)
  • UML2.0中的14种图简介,并借助AI生成UML图