Java面试题大全(每日更新)

第一天

1.重载和重写的区别?

重载发生在一个类中,同名的方法如果有不同的参数列表(类型不同、个数不同、顺序不同)则视为重载。
重写发生在子类与父类之间,重写要求子类重写之后的方法与父类被重写方法有相同的返回类型,比父类被重写方法更好访问,不能比父类被重写方法声明更多的异常。

2.String 和 StringBuffer、StringBuilder 的区别是什么?

  1. 不可变性:
  • String类是不可变的,即一旦创建了String对象,就不能修改它的值。每次对String对象的操作都会创建一个新的String对象,导致内存开销较大。
  • StringBuffer和StringBuilder类是可变的,它们允许修改已有的字符串内容。对于频繁的字符串操作,使用可变的类可以避免频繁地创建新对象,提高性能。
  1. 线程安全性:
  • String类是线程安全的,因为它的不可变性使得多个线程可以共享同一个String对象,不会出现并发修改的问题。
  • StringBuffer类是线程安全的,它的方法都是同步的(synchronized),因此多个线程可以安全地使用它进行字符串操作。但是,由于同步操作的开销,它的性能相对较低。
  • StringBuilder类是非线程安全的,它的方法没有进行同步。因此,在多线程环境下使用StringBuilder时需要自行保证线程安全。
  1. 性能:
  • 由于String类的不可变性,每次对字符串进行修改时都会创建一个新的String对象,导致频繁的内存分配和回收,对性能有一定影响。
  • StringBuffer和StringBuilder类的可变性使得它们在进行字符串操作时不会频繁创建新对象,性能较高。StringBuilder类比StringBuffer类的性能稍高,因为它的方法没有进行同步。

综上所述,如果需要频繁进行字符串操作且不涉及多线程环境,推荐使用StringBuilder类,它具有较高的性能。如果涉及多线程环境或需要线程安全,使用StringBuffer类。String类则适用于不需要修改字符串内容的情况。

3.== 与 equals 的区别?

"=="操作符:

  • 对于基本数据类型,"=="比较的是值是否相等。
  • 对于引用类型(对象),"=="比较的是对象的引用是否相等,即两个对象是否指向同一个内存地址。

"equals()"方法:

"equals()"方法是Object类的方法 , 默认情况下,Object类的"equals()“方法比较的是两个对象的引用是否相等,等价于”=="操作符。 通常,我们需要在自定义类中重写"equals()"方法,根据类的实际需求来定义两个对象是否相等的判断逻辑。 比如:String str1 = "Hello"; String str2 = new String("Hello"); boolean result = str1.equals(str2); // true

4.抽象类和接口的区别是什么?

抽象类(Abstract Class)和接口(Interface)是Java中用于实现抽象类型的两种机制,他们的区别如下:

实现:抽象类的子类使用 extends 来继承;接口必须使用 implements 来实现接口。

构造函数:抽象类可以有构造函数;接口不能有。

实现数量:类可以实现很多个接口;但只能继承一个抽象类【java只支持单继承】。

访问修饰符:接口中的方法默认使用 public 修饰;抽象类中的抽象方法可以使用Public和Protected修饰.

设计层面:抽象是对类的抽象,是一种模板设计,而接口是对行为的抽象,是一种行为的规范。

5. 面向对象的特点

面向对象编程(Object-Oriented Programming,简称OOP)具有以下特征:

封装:
封装是将数据和对数据的操作封装在一个单元中,通过定义类来实现。
类通过公共接口(方法)来控制对内部数据的访问,隐藏了内部实现的细节,提供了数据的安全性和保护。

继承:
继承是通过定义一个新的类来继承现有类的特性(属性和方法)。
继承实现了代码的重用,可以建立类之间的层次关系,并通过父类的特性扩展子类的功能。
子类可以继承并重写父类的方法,实现多态性。

多态性:
多态性指的是同一类型的对象,在不同的情境下表现出不同的行为。
多态性通过方法的重写和方法的重载实现。
多态性使得程序可以更加灵活和可扩展,提高了代码的可读性和可维护性。

这些特征共同构成了面向对象编程的核心思想和基本原则,使得代码具有可重用性、可扩展性、可维护性和可理解性。面向对象编程使得程序更易于设计、实现和维护,提高了软件开发的效率和质量。

第二天

1.Collection 和 Collections 有什么区别?

  1. Collection:
  • Collection是Java集合框架中定义的接口,它是所有集合类的根接口。
  • Collection接口提供了对一组对象进行集合操作的通用方法,如添加、删除、查找等。
  • Collection接口的常见实现类包括List、Set和Queue等。
  1. Collections:
  • Collections是Java中提供的一个工具类,包含了各种操作集合的静态方法。
  • Collections类提供了一系列静态方法,用于对集合进行排序、查找、替换、同步等操作。
  • Collections类中的方法都是通过传入集合对象作为参数来操作集合。

需要注意的是,Collection和Collections之间没有直接的继承或关联关系。Collection是一个接口,定义了集合的通用行为,而Collections是一个工具类,提供了对集合的操作方法。我们可以使用Collections类的方法对实现了Collection接口的具体集合对象进行操作。

2.List、Set、Map 之间的区别是什么?

  • List是一个有序的集合,允许元素重复,可以通过索引访问和修改元素。
  • Set是一个不允许重复元素的集合,元素无固定顺序,无法通过索引访问元素。
  • Map是一种键值对的映射结构,键唯一,值可以重复,可以通过键来获取值。

需要根据具体的需求选择适当的接口和实现类。如果需要有序的集合,可以选择List;如果需要去重的集合,可以选择Set;如果需要根据键查找对应的值,可以选择Map。

3. HashMap 和 Hashtable 有什么区别?

存储:HashMap 运行 key 和 value 为 null,而 Hashtable 不允许。
线程安全:Hashtable 是线程安全的,而 HashMap 是非线程安全的。
性能:HashMap的性能通常比Hashtable更好。Hashtable的方法是同步的,因此在单线程环境下会产生额外的性能开销。HashMap允许使用null值,避免了对null值的判断和同步操作,有利于性能优化。

4. 说一下 HashMap 的实现原理?

HashMap 基于 Hash 算法实现的,我们通过 put(key,value)存储,get(key)来获取。 当传入 key 时,HashMap 会根据 key. hashCode() 计算出 hash 值,根据 hash 值将 value 保存在 数组 里。当计算出的 hash 值相同且equals不同时,我们称之为 hash 冲突,HashMap 的 做法是用链表和红黑树存储相同 hash 值的 value。当 hash 冲突的个数比较少时,使用链表当hash冲突大于8且数组长度大于64位时使用红黑树。

5. 说一下 HashSet 的实现原理?

HashSet 是基于 HashMap 实现的,HashSet 底层使用 HashMap 来保存所有元素,因此 HashSet 的实现比较简单,相关 HashSet 的操作,基本上都是直接调用底层 HashMap 的相 关方法来完成,HashSet 不允许重复的值。

第三天

1.ArrayList和LinkedList的区别

ArrayList:基于动态数组,连续内存存储,适合下标访问(随机访问),扩容机制:因为数组长度固定,超出长度存数据时需要新建数组,然后将老数组的数据拷贝到新数组,如果不是尾部插入数据还会涉及到元素的移动(往后复制一份,插入新元素),使用尾插法并指定初始容量可以极大提升性能、甚至超过linkedList (需要创建大量的node对象)

LinkedList:基于链表,可以存储在分散的内存中,适合做数据插入及删除操作,不适合查询:需要逐一遍历,遍历LinkedList必须使用iterator,不能使用for循环,因为每次for循环体内通过get(i)取得某一元素时都需要对list重新进行遍历,性能消耗极大。

ArrayList基于动态数组实现的非线程安全的集合;LinkedList基于链表实现的非线程安全的集合。
对于随机index访问的get和set方法,一般ArrayList的速度要优于LinkedList。因为ArrayList直接通过数组下标直接找到元素;LinkedList要移动指针遍历每个元素直到找到为止。
新增和删除元素,一般LinkedList的速度要优于ArrayList。因为ArrayList在新增和删除元素时,可能扩容和复制数组;LinkedList实例化对象需要时间外,只需要修改指针即可。
LinkedList集合不支持 高效的随机访问(RandomAccess)
ArrayList的空间浪费主要体现在在list列表的结尾预留一定的容量空间,而LinkedList的空间花费则体现在它的每一个元素都需要消耗相当的空间

2. Java集合容器有哪些?

Java中的集合容器是用于存储和操作一组对象的数据结构。Java提供了许多内置的集合容器。以下是一些常见的Java集合容器:

Collection:

​ --List: 有序可重复集合接口

​ ArrayList:动态数组,可以根据需要自动增长大小。

​ LinkedList:双向链表,可以在任意位置插入和删除元素。

–Set:无序不可重复集合接口

​ HashSet:基于哈希表实现的集合,不允许重复元素。

​ TreeSet:基于红黑树实现的有序集合,按照元素的自然顺序进行排序。

​ LinkedHashSet:基于哈希表和链表实现的集合,保持元素的插入顺序。

Map: 键值对集合对象

  1. HashMap:基于哈希表实现的键值对映射,不允许重复键。
  2. TreeMap:基于红黑树实现的有序键值对映射,按照键的自然顺序进行排序。
  3. LinkedHashMap:基于哈希表和链表实现的键值对映射,保持元素的插入顺序。

以上仅是一些常见的集合容器。每种集合容器都有其特定的用途和适用场景,选择合适的容器可以提高代码效率和可读性。

3.哪些集合类是线程安全的?

Vector、Hashtable、Stack 都是线程安全的,而像 HashMap 则是非线程安全 的,不过在JDK1.5之后随着 Java.util.concurrent 并发包的出现,它们也有 了 自 己 对 应 的 线 程 安 全 类 , 比 如 HashMap 对 应 的 线 程 安 全 类 就 是 ConcurrentHashMap.

4.创建线程有哪几种方式?

创建线程有三种方式: ,,
继承 Thread 重写 run 方法;
实现 Runnable 接口;
实现 Callable 接口。

5.说一下 runnable 和 callable 有什么区别?

runnable 没有返回值,callable 可以拿到有返回值,callable 可以看作是 runnable 的补充。
1.callable 任务体有返回值
2.callable 任务体抛出异常了
3.callable 是Runnable补充

第四天

1.线程有哪些状态?

  1. 新建(New):当线程对象被创建但尚未启动时处于新建状态。
  2. 可运行(Runnable):线程对象调用了start()方法后,线程处于可运行状态。在可运行状态下,线程可能正在执行,也可能正在等待系统资源(如处理器时间片)。
  3. 运行(Running):线程获得了处理器时间片并正在执行其任务。
  4. 阻塞(Blocked):线程被阻塞并暂时停止执行,通常是因为等待某个操作的完成(如等待I/O操作、等待获取锁、等待某个条件满足等)。
  5. 等待(Waiting):线程等待某个特定条件的发生,需要其他线程显式地唤醒(如通过wait()方法)。
  6. 超时等待(Timed Waiting):线程等待一段特定的时间,超过时间后会自动唤醒。
  7. 终止(Terminated):线程执行完毕或出现异常导致终止,不再可运行。

2.sleep() 和wait() 有什么区别?

类的不同:sleep() 来自 Thread,wait() 来自 Object。
释放锁:sleep() 不释放锁;wait() 释放锁。
用 法 不 同 : sleep() 时 间 到 会 自 动 恢 复 ; wait() 可 以 使 用 notify()/notifyAll()直接唤醒。

3.notify()和 notifyAll()有什么区别?

notifyAll()会唤醒所有的线程,notify()只会唤醒一个线程。notifyAll() 调用后, 会将全部线程由等待池移到锁池,然后参与锁的竞争,竞争成功则继续执行,如果不成功则 留在锁池等待锁被释放后再次参与竞争。而 notify()只会唤醒一个线程,具体唤醒哪一个 线程由虚拟机控制。

4.线程的 run() 和 start() 有什么区别?

start() 方法用于启动线程,run() 方法用于执行线程的运行时代码。run() 可以重复 调用,而 start() 只能调用一次。

5.说一说几种常见的线程池及适用场景?

  1. 固定大小线程池(FixedThreadPool):
    • 特点:创建一个固定大小的线程池,线程数量固定,任务提交后会一直保持执行状态,直到线程池关闭。
    • 适用场景:适用于需要限制并发线程数量的场景,如服务器后台处理任务、Web服务器。
  2. 缓存线程池(CachedThreadPool):
    • 特点:创建一个可以动态调整大小的线程池,根据任务的数量自动增加或减少线程数量。
    • 适用场景:适用于需要处理大量短期任务的场景,如异步任务处理、大量并发请求的服务器。
  3. 单线程线程池(SingleThreadExecutor):
    • 特点:只有一个工作线程的线程池,任务按顺序执行,保证任务的顺序性。
    • 适用场景:适用于需要顺序执行任务的场景。
  4. 调度线程池(ScheduledThreadPool):
    • 特点:用于定时执行任务和周期性执行任务的线程池。
    • 适用场景:适用于需要定时执行或周期性执行任务的场景,如定时任务调度、定时数据备份。

第五天

1.线程池中 submit() 和execute() 方法有什么区别?

execute():只能执行 Runnable 类型的任务。

submit():可以执行 Runnable 和 Callable 类型的任务。

Callable 类型的任务可以获取执行的返回值,而 Runnable 执行无返回值。

2.在 Java 程序中怎么保证多线程的运行安全?

方法一:使用安全类,比如 Java. util. concurrent 下的类。
方法二:使用自动锁 synchronized。
方法三:使用手动锁 Lock

3.什么是死锁?

当线程 A 持有独占锁 a,并尝试去获取独占锁 b 的同时,线程 B 持有独
占锁 b,并 尝试获取独占锁 a 的情况下,就会发生 AB 两个线程由于互
相持有对方需要的锁,而发生 的阻塞现象,我们称为死锁。

死锁是一组相互竞争资源的线程因为他们之间得到互相等待导致“永久“阻塞的现象; (你等我 我等你 你不放我也不放 就导致“永久“阻塞的现象)

4.怎么防止死锁?

尽量使用 tryLock(long timeout, TimeUnit unit)的方法(ReentrantLock ReentrantReadWriteLock),设置超时时间,超时可以退出防止死锁。

尽量使用 Java. util. concurrent 并发类代替自己手写锁。

尽量降低锁的使用粒度,尽量不要几个功能用同一把锁。

尽量减少同步的代码块。

5.ThreadLocal 是什么?有哪些使用场景?

ThreadLocal 为每个使用该变量的线程提供独立的变量副本,所以每一个线程都可以独 立地改变自己的副本,而不会影响其它线程所对应的副本。

ThreadLocal 的经典使用场景是数据库连接和 session 管理等。

第六天

1.synchronized 和 Lock 有什么区别?

  • synchronized 可以给类、方法、代码块加锁;而 lock 只能给代码块加锁。
  • synchronized 不需要手动获取锁和释放锁,使用简单,发生异常会自动释放 锁,不会造成死锁;而 lock 需要自己加锁和释放锁,如果使用不当没有 unLock() 去释放锁就会造成死锁。
  • 通过 Lock 可以知道有没有成功获取锁,而 synchronized 却无法办到。

2.什么是 Java 序列化?什么情况下需要序列化?

Java 序列化是为了保存各种对象在内存中的状态,并且可以把保存的对象状态再读出来。

以下情况需要使用 Java 序列化:

  • 想把的内存中的对象状态保存到一个文件中或者数据库中时候;
  • 想用套接字在网络上传送对象的时候;
  • 想通过 RMI(远程方法调用)传输对象的时候。

3.动态代理是什么?有哪些应用?

动态代理是运行时动态生成代理类。

应用:
动态代理的应用有 spring aop、rpc, Java 注解对象获取等。

4.怎么实现动态代理?

JDK 原生动态代理和 cglib 动态代理。JDK 原生动态代理是基于接口实现的,而 cglib 是基于继承当前类的子类实现的。

5.为什么要使用克隆?

克隆的对象可能包含一些已经修改过的属性,而 new 出来的对象的属性都还是初始化 时候的值,所以当需要一个新的对象来保存当前对象的“状态”就靠克隆方法了。

第七天

1.session 和 cookie 有什么区别?

存储位置不同:session 存储在服务器端;cookie 存储在浏览器端。
安全性不同:cookie 安全性一般,在浏览器存储,可以被伪造和修改。
容量和个数限制:cookie 有容量限制,每个站点下的 cookie 也有个数限制。
存储的多样性:session 可以存储在 Redis 中、数据库中、应用程序中;而 cookie 只能存储在浏览器中。

2.如何避免 SQL 注入?

使用预处理 PreparedStatement。

使用正则表达式过滤掉字符中的特殊字符。

3.throw 和 throws 的区别?

throw 和 throws 是两个在 Java 中用于处理异常的关键字,它们的作用不同,有以下的区别:

  1. 语法形式不同:throw 是一个关键字,用于抛出一个异常;而 throws 是一个关键字,用于声明一个方法可能会抛出某些类型的异常。

  2. 用途不同:throw 用于在代码块中手动抛出异常,可以用于自定义异常;而 throws 是用于在方法中声明可能会抛出异常,用于向上层的调用者传递异常信息。

  3. 必要性不同:throw 是可选的,可以手动抛出异常,也可以通过条件判断等方式自动抛出异常;而 throws 是必需的,如果一个方法中有可能抛出异常,就必须使用 throws 声明,以便捕获和处理异常。

  4. 抛出对象不同:throw 抛出的是一个异常对象,而 throws 声明的是一种可能会抛出的异常类型。

总结来说,throw 和 throws 是 Java 中用于异常处理的关键字,但它们的作用不同:throw 用于手动抛出异常对象;而 throws 用于在方法中声明可能会抛出的异常类型,向上一层传递异常信息。在实际开发中,它们通常一起使用,以实现代码的健壮性和可维护性。

4.final、finally、finalize 有什么区别?

final:是修饰符,如果修饰类,此类不能被继承;如果修饰方法和变量,则 表示此方法和此变量不能在被改变,只能使用。

finally:是 try{} catch{} finally{} 最后一部分,表示不论
发生任何情况 都会执行,finally 部分可以省略,但如果 finally 部分存在,则一定会执行 finally 里面的代码。

finalize: 是 Object 类的一个方法,在垃圾收集器执行的时候会调用被回 收对象的此方法。

5.常见的异常类有哪些?

NullPointerException 空指针异常

ClassNotFoundException 指定类不存在

NumberFormatException 字符串转换为数字异常

IndexOutOfBoundsException 数组下标越界异常

ClassCastException 数据类型转换异常

FileNotFoundException 文件未找到异常

NoSuchMethodException 方法不存在异常

IOException IO异常

SocketException Socket 异常

第八天

1.说一下你熟悉的设计模式?

单例模式:保证被创建一次,节省系统开销。

工厂模式(简单工厂、抽象工厂):解耦代码。

观察者模式:定义了对象之间的一对多的依赖,这样一来,当一个对象改变时, 它的所有的依赖者都会收到通知并自动更新。

外观模式 :提供一个统一的接口,用来访问子系统中的一群接口,外观定义了 一个高层的接口,让子系统更容易使用。

模版方法模式 :定义了一个算法的骨架,而将一些步骤延迟到子类中,模版方 法使得子类可以在不改变算法结构的情况下,重新定义算法的步骤。

代理模式:代理模式给某一个对象提供一个代理对象,并由代理对象控制对原对象的引用

2.spring框架使用了那些设计模式

  1. spring的bean的创建默认使用单例模式

  2. spring中获取bean对象通过的是工厂模式

  3. spring的aop采用的是动态代理模式

  4. 在各种BeanFactory以及ApplicationContext实现中也都用到模板模式;

3.为什么要使用 spring?

spring 提供 ioc 技术,容器会帮你管理依赖的对象,从而不需要自己创建和 管理依赖对象了,更轻松的实现了程序的解耦。

spring 提供了事务支持,使得事务操作变的更加方便。

spring 提供了面向切片编程,这样可以更方便的处理某一类的问题。

更方便的框架集成,spring 可以很方便的集成其他框架,比如MyBatis、 hibernate 等。

4.spring 常用的注入方式有哪些?

setter 属性注入

构造方法注入

注解方式注入

5.spring 事务实现方式有哪些?

声明式事务:声明式事务也有两种实现方式,基于 xml 配置文件的方式和注 解方式(在类上添加 @Transaction 注解)。

编码方式:提供编码的形式管理和维护事务。

第九天

1.并发事务会带来哪些问题?

脏读(Dirty read): 当一个事务正在访问数据并且对数据进行了修改,而这种修改还没有提交到数据库中,这时另外一个事务也访问了这个数据,然后使用了这个数据。因为这个数据是还没有提交的数据,那么另外一个事务读到的这个数据是“脏数据”,依据“脏数据”所做的操作可能是不正确的。

丢失修改(Lost to modify): 指在一个事务读取一个数据时,另外一个事务也访问了该数据,那么在第一个事务中修改了这个数据后,第二个事务也修改了这个数据。这样第一个事务内的修改结果就被丢失,因此称为丢失修改。 例如:事务1读取某表中的数据A=20,事务2也读取A=20,事务1修改A=A-1,事务2也修改A=A-1,最终结果A=19,事务1的修改被丢失。

不可重复读(Unrepeatableread): 指在一个事务内多次读同一数据。在这个事务还没有结束时,另一个事务也访问该数据。那么,在第一个事务中的两次读数据之间,由于第二个事务的修改导致第一个事务两次读取的数据可能不太一样。这就发生了在一个事务内两次读到的数据是不一样的情况,因此称为不可重复读。

幻读(Phantom read): 幻读与不可重复读类似。它发生在一个事务(T1)读取了几行数据,接着另一个并发事务(T2)插入了一些数据时。在随后的查询中,第一个事务(T1)就会发现多了一些原本不存在的记录,就好像发生了幻觉一样,所以称为幻读。

2.事务的隔离级别有哪些?

READ-UNCOMMITTED(读取未提交): 最低的隔离级别,允许读取尚未提交的数据变更,可能会导致脏读、幻读或不可重复读。

READ-COMMITTED(读取已提交): 允许读取并发事务已经提交的数据,可以阻止脏读,但是幻读或不可重复读仍有可能发生。

REPEATABLE-READ(可重复读): 对同一字段的多次读取结果都是一致的,除非数据是被本身事务自己所修改,可以阻止脏读和不可重复读,但幻读仍有可能发生。

SERIALIZABLE(可串行化): 最高的隔离级别,完全服从ACID的隔离级别。所有的事务依次逐个执行,这样事务之间就完全不可能产生干扰,也就是说,该级别可以防止脏读、不可重复读以及幻读。

3.说一下 spring mvc 运行流程?

spring mvc 先将请求发送给 DispatcherServlet。

DispatcherServlet 查询一个或多个 HandlerMapping,找到处
理请求的 Controller。

DispatcherServlet 再把请求提交到对应的 Controller。

Controller 进行业务逻辑处理后,会返回一个 ModelAndView。

Dispathcher 查 询 一 个 或 多 个 ViewResolver 视 图 解
析 器 , 找 到 ModelAndView 对象指定的视图对象。

视图对象负责渲染返回给客户端。

4.spring mvc 有哪些组件?

前置控制器 DispatcherServlet。

映射控制器 HandlerMapping。

处理器 Controller。

模型和视图 ModelAndView。

视图解析器 ViewResolver。

5.springmvc常见的注解

@Controller 作用在类上表示该类为控制层类

@RequestMapping用来处理请求地址映射的注解

@PathVariable用于将请求URL中的模板变量映射到功能处理方法的参数上,即取出uri模板中的变量作为参数

@requestParam主要用于在SpringMVC后台控制层获取参数值

@ResponseBody该注解用于将Controller的方法返回的对象转换为json格式

@RequestBody用于接收前端传来的json实体,接收参数也是对应的实体

第十天

1.什么是 spring boot以及作用?

springboot是为spring服务的,是用来简化新spring应用的初始搭建以及开发过程的。

作用:

  • 配置简单
  • 独立运行
  • 自动装配
  • 无代码生成和xml配置
  • 提供应用监控
  • 易上手
  • 提升开发效率

2.spring boot 核心配置文件是什么?

springboot核心的两个配置文件:

bootstrap(.yml或者.properties):boostrap由父ApplicationContext加载的,比applicaton优先加载,且boostrap里面的属性不能被覆盖;

application(.yml或者.properties):用于springboot 项目的自动化配置。

3.springboot自动装配原理

里面有一个main方法运行了一个run()方法,在run方法中必须要传入一个被@SpringBootApplication注解的类。
@SpringBootApplication包含@EnableAutoConfiguration该注
解,@EnableAutoConfiguration开启自动配置功能,在
@EnableAutoConfiguration中包含
@Import({AutoConfigurationImportSelector.class})注解,该注解需要导入AutoConfigurationImportSelector自动配置选择器类,该类会自动装载一些自动配置类。而这些配置类会完成相应的自动装配。

4.什么是 spring cloud?

springcloud是一系列框架的有序集合。它利用springboot的开发便利性巧妙地简化了分布式系统基础设施的开发,如服务发现注册、配置中心、消息总线、负载均衡、断路器、数据监控等,都可以用springboot的开发风格做到一键启动和部署。

5.spring cloud 的核心组件有哪些?

nacos:服务注册与发现。

Feign:基于动态代理机制,根据注解和选择的机器,拼接请求url地址,发起请求。

Ribbon:实现负载均衡,从一个服务的多台机器中选择一台。

Sentinel:提供了流量控制、熔断降级、系统负载保护等多个维度来保障服务之间的稳定性。

Gateway:网关管理,由gateway网关转发请求给对应的服务。

sleuth+zipkin——链路追踪

第十一天

1.MyBatis 中 #{}和 ${}的区别是什么?

#{}是预编译处理,${}是字符替换。 在使用 #{}时,MyBatis 会将 SQL 中的 #{} 替换成“?”,配合 PreparedStatement 的 set 方法赋值,这样可以有效的防止 SQL 注入, 保证程序的运行安全。

2.什么地方使用${}

$ 的作用是字符拼接,不能防止sql注入,当使用${}参数作为字段名或表名时使用。
比如:
select * from $ {tableName}
比如我要用 $ {}在MyBatis的sql中拼接排序类型的时候

3.当实体类的属性名和表中的字段名不一致如何处理

通过在查询的sql语句中定义字段名的别名,让字段名的别名和实体类的属性名一致。

通过 resultMap 类映射字段名和实体类属性名的一一对应的关系

4.MyBatis如何实现一对多

再resultMap中使用collection标签

在这里插入图片描述

5.ResultType和ResultMap的区别

1、resultmap:resultMap如果查询出来的列名和pojo的属性名不一致,通过定义一个resultMap对列名和pojo属性名之间作一个映射关系。

2、resulttype:resultType使用resultType进行输出映射,只有查询出来的列名和pojo中的属性名一致,该列才可以映射成功。

第十二天

1.Redis 是什么?都有哪些使用场景?

Redis 是一个使用 C 语言开发的高速缓存数据库。

Redis 使用场景:

  • 记录帖子点赞数、点击数、评论数;
  • 缓存近期热点数据;
  • 记录用户会话信息。

2. Redis 有哪些功能?

  • 数据缓存功能
  • 分布式锁的功能
  • 支持数据持久化
  • 解决分布式会话

3.什么是缓存穿透?怎么解决?

缓存穿透:指查询一个一定不存在的数据,由于缓存是不命中时需要从数据库查询,查 不到数据则不写入缓存,这将导致这个不存在的数据每次请求都要到数据库去查询,造成缓 存穿透

解决:

  1. 最常见的则是采用布隆过滤器,将所有可能存在的数据哈希到一个足够大的bitmap中,一个一定不存在的数据会被 这个bitmap拦截掉,从而避免了对底层存储系统的查询压力。
  2. 另外也有一个更为简单粗暴的方法(我们采用的就是这种),如果一个查询返回的数据为空(不管是数据不存在,还是系统故障),我们仍然把这个空结果进行缓存,但它的过期时间会很短,最长不超过五分钟。

4.什么是缓存击穿?如何解决?

缓存击穿是指缓存中没有但数据库中有的数据(一般是缓存时间到期),这时由于并发用户特别多,同时读缓存没读到数据,又同时去数据库去取数据,引起数据库压力瞬间增大,造成过大压力。

缓存击穿解决方案:
1.设置永久不过期。【这种只适合】
2.使用互斥锁(mutex key)业界比较常用的做法,是使用mutex。简单地来说,就是在缓存失效的时候(判断拿出来的值为空),不是立即去load db,而是先使用缓存工具的某些带成功操作返回值的操作(比如Redis的SETNX或者Memcache的ADD)去set一个mutex key,当操作返回成功时,再进行load db的操作并回设缓存;否则,就重试整个get缓存的方法。代码如下:

public String get(key) {
      String value = redis.get(key);
      if (value == null) { //代表缓存值过期
          //设置3min的超时,防止del操作失败的时候,下次缓存过期一直不能load db
      if (redis.setnx(key_mutex, 1, 3 * 60) == 1) {  //代表设置成功
               value = db.get(key);
                      redis.set(key, value, expire_secs);
                      redis.del(key_mutex);
              } else {  //这个时候代表同时候的其他线程已经load db并回设到缓存了,这时候重试获取缓存值即可
                      sleep(50);
                      get(key);  //重试
              }
          } else {
              return value;      
          }
 }

5. 什么是缓存雪崩?如何解决?

缓存雪崩是指缓存中数据大批量到过期时间,而查询数据量巨大,引起数据库压力过大甚至down机。和缓存击穿不同的是, 缓存击穿指并发查同一条数据,缓存雪崩是不同数据都过期了,很多数据都查不到从而查数据库。

解决方案:

1.缓存数据的过期时间设置随机,防止同一时间大量数据过期现象发生。
2.如果缓存数据库是分布式部署,将热点数据均匀分布在不同搞得缓存数据库中。
3.设置热点数据永远不过期。

6.Redis 支持的数据类型有哪些?

Redis 支持的数据类型:string(字符串)、list(列表)、hash(字典)、set(集 合)、zset(有序集合)。

7.怎么保证缓存和数据库数据的一致性?

  • 合理设置缓存的过期时间。
  • 新增、更改、删除数据库操作时同步更新 Redis,可以使用事物机制来保证 数据的一致性。

8.Redis 持久化有几种方式?

Redis 的持久化有两种方式,或者说有两种策略:

  • RDB(Redis Database):指定的时间间隔能对你的数据进行快照存储。
  • AOF(Append Only File):每一个收到的写命令都通过 write 函数追加到文 件中。

9.Redis 怎么实现分布式锁?

Redis 分布式锁其实就是在系统里面占一个“坑”,其他程序也要占“坑”的时候,占 用成功了就可以继续执行,失败了就只能放弃或稍后重试。
占坑一般使用 setnx(set if not exists)指令,只允许被一个程序占有,使用完调用 del 释放锁。

10.Redis 淘汰策略有哪些?

volatile-lru:从已设置过期时间的数据集(server. db[i]. expires)中挑 选最近最少使用的数据淘汰。

volatile-ttl:从已设置过期时间的数据集(server. db[i]. expires)中挑 选将要过期的数据淘汰。

volatile-random:从已设置过期时间的数据集(server. db[i]. expires)中 任意选择数据淘汰。

allkeys-lru:从数据集(server. db[i]. dict)中挑选最近最少使用的数据 淘汰。

allkeys-random:从数据集(server. db[i]. dict)中任意选择数据淘汰。

no-enviction(驱逐):禁止驱逐数据。

第十三天

1. Spring的IoC理解:

(1)什么是IOC:
IOC,Inversion of Control,控制反转,指将对象的控制权转移给Spring框架,由 Spring 来负责控制对象的生命周期(比如创建、销毁)和对象间的依赖关系。
(2)什么是DI:
IoC 的一个重点就是在程序运行时,动态的向某个对象提供它所需要的其他对象,这一点是通过DI(Dependency Injection,依赖注入)来实现的,即应用程序在运行时依赖 IoC 容器来动态注入对象所需要的外部依赖。而 Spring 的 DI 具体就是通过反射实现注入的,反射允许程序在运行的时候动态的生成对象、执行对象的方法、改变对象的属性.
(3)IoC的原理:
Spring 的 IoC 的实现原理就是工厂模式加反射机制。

2.Spring的AOP理解:

OOP面向对象,允许开发者定义纵向的关系,但并不适用于定义横向的关系,会导致大量代码的重复,而不利于各个模块的重用。

AOP,一般称为面向切面,作为面向对象的一种补充,用于将那些与业务无关,但却对多个对象产生影响的公共行为和逻辑,抽取并封装为一个可重用的模块,这个模块被命名为“切面”(Aspect),减少系统中的重复代码,降低了模块间的耦合度,提高系统的可维护性。可用于权限认证、日志、事务处理。

3.BeanFactory和ApplicationContext有什么区别?

BeanFactory和ApplicationContext是Spring的两大核心接口,都可以当做Spring的容器。
(1)BeanFactory是Spring里面最底层的接口,是IoC的核心,定义了IoC的基本功能,ApplicationContext接口作为BeanFactory的子类,除了提供BeanFactory所具有的功能外,还提供了更完整的框架功能。

(2)BeanFactroy采用的是延迟加载形式来注入Bean的,只有在使用到某个Bean时(调用getBean()),才对该Bean进行加载实例化。ApplicationContext,它是在容器启动时,一次性创建了所有的Bean。

(3)BeanFactory通常以编程的方式创建,ApplicationCotext还能以声明的方式创建。

4.Spring通知(Advice)有哪些类型?

(1)前置通知(Before Advice):在连接点(Join point)之前执行的通知。

(2)后置通知(After Advice):当连接点退出的时候执行的通知(不论是正常返回还是异常退出)。

(3)环绕通知(Around Advice):包围一个连接点的通知,这是最强大的一种通知类型。 环绕通知可以在方法调用前后完成自定义的行为。它也可以选择是否继续执行连接点或直接返回它们自己的返回值或抛出异常来结束执行。

(4)返回后通知(AfterReturning Advice):在连接点正常完成后执行的通知(如果连接点抛出异常,则不执行)

(5)抛出异常后通知(AfterThrowing advice):在方法抛出异常退出时执行的通知

5. Spring中bean的作用域:

(1)singleton:默认作用域,单例bean,每个容器中只有一个bean的实例。

(2)prototype:为每一个bean请求创建一个实例。

(3)request:为每一个request请求创建一个实例,在请求完成以后,bean会失效并被垃圾回收器回收。

(4)session:与request范围类似,同一个session会话共享一个实例,不同会话使用不同的实例。

(5)global-session:全局作用域,所有会话共享一个实例。如果想要声明让所有会话共享的存储变量的话,那么这全局变量需要存储在global-session中。

第十四天

1.Spring框架中的Bean是线程安全的么?如果线程不安全,那么如何处理?

Spring容器本身并没有提供Bean的线程安全策略,因此可以说Spring容器中的Bean本身不具备线程安全的特性,但是具体情况还是要结合Bean的作用域来讨论。

(1)对于prototype作用域的Bean,每次都创建一个新对象,也就是线程之间不存在Bean共享,因此不会有线程安全问题。

(2)对于singleton作用域的Bean,所有的线程都共享一个单例实例的Bean,因此是存在线程安全问题的。但是如果单例Bean是一个无状态Bean,也就是线程中的操作不会对Bean的成员执行查询以外的操作,那么这个单例Bean是线程安全的。比如Controller类、Service类和Dao等,这些Bean大多是无状态的,只关注于方法本身。

对于有状态的bean(比如Model和View),就需要自行保证线程安全,最浅显的解决办法就是将有状态的bean的作用域由“singleton”改为“prototype”。

也可以采用ThreadLocal解决线程安全问题,为每个线程提供一个独立的变量副本,不同线程只操作自己线程的副本变量。

ThreadLocal和线程同步机制都是为了解决多线程中相同变量的访问冲突问题。同步机制采用了“时间换空间”的方式,仅提供一份变量,不同的线程在访问前需要获取锁,没获得锁的线程则需要排队。而ThreadLocal采用了“空间换时间”的方式。ThreadLocal会为每一个线程提供一个独立的变量副本,从而隔离了多个线程对数据的访问冲突。因为每一个线程都拥有自己的变量副本,从而也就没有必要对该变量进行同步了。

2.Spring基于xml注入bean的几种方式:

  • set()方法注入;
  • 构造器注入:①通过index设置参数的位置;②通过type设置参数类型;
  • 静态工厂注入;
  • 实例工厂;

3.Spring的自动装配:

在spring中,使用autowire来配置自动装载模式,对象无需自己查找或创建与其关联的其他对象,由容器负责把需要相互协作的对象引用赋予各个对象。

(1)在Spring框架xml配置中共有5种自动装配:

no:默认的方式是不进行自动装配的,通过手工设置ref属性来进行装配bean。
byName:通过bean的名称进行自动装配,如果一个bean的 property 与另一bean 的name 相同,就进行自动装配。
byType:通过参数的数据类型进行自动装配。
constructor:利用构造函数进行装配,并且构造函数的参数通过byType进行装配。
autodetect:自动探测,如果有构造方法,通过 construct的方式自动装配,否则使用 byType的方式自动装配。
(2)基于注解的自动装配方式:

使用@Autowired、@Resource注解来自动装配指定的bean。

4. @Autowired和@Resource之间的区别.

(1) @Autowired默认是按照类型装配注入的,默认情况下它要求依赖对象必须存在(可以设置它required属性为false)。

(2) @Resource默认是按照名称来装配注入的,只有当找不到与名称匹配的bean才会按照类型来装配注入。

5.说一下Spring的事务传播行为

spring事务的传播行为说的是,当多个事务同时存在的时候,spring如何处理这些事务的行为。

① REQUIRED:如果当前没有事务,就创建一个新事务,如果当前存在事务,就加入该事务,该设置是最常用的设置。

② SUPPORTS:支持当前事务,如果当前存在事务,就加入该事务,如果当前不存在事务,就以非事务执行。

③ MANDATORY:支持当前事务,如果当前存在事务,就加入该事务,如果当前不存在事务,就抛出异常。

④ REQUIRES_NEW:创建新事务,无论当前存不存在事务,都创建新事务。

⑤ NOT_SUPPORTED:以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。

⑥ NEVER:以非事务方式执行,如果当前存在事务,则抛出异常。

⑦ NESTED:如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则按REQUIRED属性执行。

第十五天

1.通常一个mapper.xml文件,都会对应一个Dao接口,这个Dao接口的工作原理是什么?Dao接口里的方法,参数不同时,方法能重载吗?

Mapper 接口的工作原理是JDK动态代理,Mybatis运行时会使用JDK动态代理为Mapper接口生成代理对象 MappedProxy,代理对象会拦截接口方法,根据类的全限定名+方法名,唯一定位到一个MapperStatement并调用执行器执行所代表的sql,然后将sql执行结果返回。

2.Mybatis是否支持延迟加载?如果支持,它的实现原理是什么?

Mybatis仅支持association关联对象和collection关联集合对象的延迟加载,association指的就是一对一,collection指的就是一对多查询。在Mybatis配置文件中,可以配置是否启用延迟加载lazyLoadingEnabled=true|false。

延迟加载的基本原理是,使用CGLIB创建目标对象的代理对象,当调用目标方法时,进入拦截器方法,比如调用a.getB().getName(),拦截器invoke()方法发现a.getB()是null值,那么就会单独发送事先保存好的查询关联B对象的sql,把B查询上来,然后调用a.setB(b),于是a的对象b属性就有值了,接着完成a.getB().getName()方法的调用

3.Mybatis的一级、二级缓存:

(1)一级缓存: 基于 PerpetualCache 的 HashMap 本地缓存,其存储作用域为 Session,当 Session flush 或 close 之后,该 Session 中的所有 Cache 就将清空,默认打开一级缓存。

(2)二级缓存与一级缓存其机制相同,默认也是采用 PerpetualCache,HashMap 存储,不同在于其存储作用域为 Mapper(Namespace),并且可自定义存储源,如 Ehcache。默认不打开二级缓存,要开启二级缓存,使用二级缓存属性类需要实现Serializable序列化接口(可用来保存对象的状态),可在它的映射文件中配置 ;

(3)对于缓存数据更新机制,当某一个作用域(一级缓存 Session/二级缓存Namespaces)的进行了C/U/D 操作后,默认该作用域下所有 select 中的缓存将被 clear 掉并重新更新,如果开启了二级缓存,则只根据配置判断是否刷新。

4.Xml映射文件中,除了常见的select|insert|updae|delete标签外,还有哪些标签?

、、、、,加上动态sql的9个标签 trim | where | set | foreach | if | choose | when | otherwise | bind 等,其中 为sql片段标签,通过标签引入sql片段,为不支持自增的主键生成策略标签。

5.在mapper中如何传递多个参数?

(1)第一种:
//DAO层的函数
Public UserselectUser(String name,String area);
//对应的xml,#{0}代表接收的是dao层中的第一个参数,#{1}代表dao层中第二参数,更多参数一致往后加即可。
<select id="selectUser"resultMap=“BaseResultMap”>
select * fromuser_user_t whereuser_name = #{0} anduser_area=#{1}

(2)第二种: 使用 @param 注解:
public interface usermapper {
user selectuser(@param(“username”) string username,@param(“hashedpassword”) string hashedpassword);
}
然后,就可以在xml像下面这样使用(推荐封装为一个map,作为单个参数传递给mapper):

select id, username, hashedpassword
from some_table
where username = #{username}
and hashedpassword = #{hashedpassword}

(3)第三种:多个参数封装成map
try{
//映射文件的命名空间.SQL片段的ID,就可以调用对应的映射文件中的SQL
//由于我们的参数超过了两个,而方法中只有一个Object参数收集,因此我们使用Map集合来装载我们的参数
Map<String, Object> map = new HashMap();
map.put(“start”, start);
map.put(“end”, end);
return sqlSession.selectList(“StudentID.pagination”, map);
}catch(Exception e){
e.printStackTrace();
sqlSession.rollback();
throw e; }
finally{
MybatisUtil.closeSqlSession();
}

第十六天

1. Spring @bean 和 @component 注解有什么区别

  1. 作用对象不同: @Component 注解作用于类,而 @Bean 注解作用于方法、
  2. @Component 通常是通过路径扫描来自动侦测以及自动装配到 Spring 容器中(我们可以使用@ComponentScan 注解定义要扫描的路径从中找出标识了需要装配的类自动装配到 Spring的 bean 容器中)。 @Bean 注解通常是我们在标有该注解的方法中定义产生这个 bean,@Bean 告诉了 Spring 这是某个类的实例,当我们需要用它的时候还给我。
  3. @Bean 注解比 @Component 注解的自定义性更强,而且很多地方我们只能通过 @Bean 注解来注册 bean。比如当我们引用第三方库中的类需要装配到 Spring 容器时,只能通过 @Bean来实现。

2. springbean的生命周期

Spring Framework中的Bean(即Spring Bean)生命周期是指一个Bean从被创建到被销毁的整个过程。Spring框架通过提供各种回调方法和扩展点来管理Bean的生命周期,以便在Bean的不同生命周期阶段执行特定的操作。以下是Spring Bean的典型生命周期:

  1. 实例化(Instantiation):在这个阶段,Spring容器会创建Bean的实例。这通常涉及使用构造函数创建一个新的Bean实例。
  2. 属性赋值(Population of Properties):在这个阶段,Spring容器会将配置的属性值注入到Bean中,可以通过构造函数注入、属性注入或者方法注入来完成。
  3. 初始化(Initialization):一旦属性赋值完成,Spring容器会调用Bean的初始化方法(如果有定义的话)。开发人员可以通过实现 InitializingBean 接口或在配置文件中指定initmethod来指定初始化方法。
  4. 使用(In Use):在这个阶段,Bean已经完全初始化,可以被应用程序使用。
  5. 销毁(Destruction):当Bean不再需要时,Spring容器会调用Bean的销毁方法(如果有定义的话)。开发人员可以通过实现 DisposableBean 接口或在配置文件中指定destroymethod来指定销毁方法。

需要注意的是,Spring容器并不总是管理Bean的整个生命周期,它只管理由Spring容器创建的Bean。对于单例(Singleton)作用域的Bean,Spring容器会在应用程序关闭时销毁这些Bean。对于其他作用域(如原型Prototype)的Bean,开发人员需要手动管理其生命周期。

总之,Spring框架通过回调方法和配置选项,为Bean的实例化、属性赋值、初始化、使用和销毁提供了强大的控制和扩展能力,使开发人员能够更灵活地管理应用程序中的Bean。

3. springbean的循环依赖以及如何解决

循环依赖是指两个或多个Bean之间相互引用,形成了一个循环引用链。这种情况下,Spring容器无法完成Bean的正常创建和初始化,因为每个Bean都需要依赖于其他Bean,但其他Bean也尚未完全创建。这可能导致应用程序启动失败或不稳定的情况。
Spring提供了一些机制来解决循环依赖问题:

  1. 构造函数注入:使用构造函数注入来解决循环依赖是最佳实践。如果循环依赖的Bean之间的关系是通过构造函数进行注入的,Spring会通过传递部分创建好的Bean实例来解决循环依赖。
  2. 延迟初始化:通过设置Bean的 lazy-init 属性为true,可以延迟Bean的初始化,从而打破循环依赖链。但是这种方法并不总是可行,因为某些情况下可能需要在应用程序启动时立即初始化一些Bean。
  3. Setter方法注入:如果使用Setter方法注入属性,Spring会先完成Bean的实例化并设置依赖,然后再执行初始化方法。虽然Setter方法注入可以解决某些循环依赖问题,但是在很多情况下可能并不适用。
  4. 使用代理:Spring可以使用代理来解决某些循环依赖问题。通过在循环依赖的Bean中使用代理,可以推迟依赖的实际创建和初始化。
  5. 使用@DependsOn注解: @DependsOn 注解可以用于指定Bean的依赖顺序,从而显式地告诉Spring容器哪些Bean需要在其他Bean之前初始化。
    解决循环依赖问题时,首先要考虑的是应用程序的设计是否合理。循环依赖通常是代码结构或设计模式不佳的结果,因此在解决循环依赖问题之前,可能需要重新考虑应用程序的架构和依赖关系。

尽管Spring提供了这些解决方案,但最好的方法是尽量避免循环依赖,保持Bean之间的清晰和分离。在设计和开发过程中,应该注意遵循良好的编程实践,避免产生复杂的循环依赖链

4. spring事务失效的场景

Spring事务可能会失效的一些场景包括:

  1. 不被Spring管理的方法调用:只有通过Spring容器管理的方法调用才能触发事务切面。如果在没有Spring代理的情况下调用了带有事务注解的方法,事务将不会起作用。
  2. 运行时异常没有被抛出:Spring的事务是基于异常回滚的机制。如果在方法内部捕获了运行时异常,并没有将其继续抛出,事务将无法感知到异常并进行回滚。
  3. 事务属性设置不正确:使用错误的事务传播行为或隔离级别可能会导致事务失效。例如,将一个事务性方法内部调用另一个事务性方法,并将传播行为设置为 REQUIRED ,这会导致内部方法的事务失效,因为它会加入外部方法的事务。
  4. 非受检异常:如果一个方法抛出的异常不是Spring事务管理器中配置的受检异常之一(通常是继承自 RuntimeException 的异常),事务可能不会触发回滚。
  5. 异步方法:使用 @Async 注解的方法将异步执行,不会阻塞调用者,因此事务可能在异步方法中失效。要在异步方法中启用事务,可以使用
    TransactionAspectSupport.currentTransactionStatus().setRollbackOnly() 来手动设置回滚标志。
  6. Self调用:如果一个事务性方法内部通过对象的引用直接调用了自己,Spring的事务代理将无法拦截该调用,因为它会绕过代理。
  7. 内部方法调用不触发代理:如果一个事务性方法内部调用了同一个类中的另一个方法,而调用方法没有使用代理对象进行调用,事务可能会失效。
  8. 事务隔离级别问题:事务的隔离级别设置不正确可能会导致并发问题和脏读,影响事务的有效性。为了避免这些问题,确保你的代码和事务配置是正确的,并且遵循Spring的最佳实践。在遇到事务失效的问题时,可以仔细检查日志,确认事务是否被正确地启用和触发,以及检查相关的代码和配置是否符合事务管理的要求。

5. springboot常见注解

Spring Boot 是基于 Spring 框架的扩展,通过一些常用的注解来简化配置和开发。以下是一些常
见的 Spring Boot 注解:

  1. @SpringBootApplication: 这是一个组合注解,等价于 @Configuration 、
    @EnableAutoConfiguration 和 @ComponentScan 。用于标识主应用程序类,并指示
    Spring Boot 自动进行配置和组件扫描。
  2. @RestController: 用于定义一个控制器类,其中的方法默认返回 JSON 格式的响应,通常用
    于构建 RESTful API。
  3. @RequestMapping: 定义处理请求的方法,可以用于类级别和方法级别,用于映射 URL 路
    径到方法。
  4. @GetMapping, @PostMapping, @PutMapping, @DeleteMapping: 这些注解分别对应
    HTTP 的 GET、POST、PUT 和 DELETE 请求,用于更明确地定义处理不同类型请求的方法。
  5. @RequestParam: 用于从请求参数中获取值。
  6. @PathVariable: 用于从 URL 路径中获取值。
  7. @RequestBody: 用于将请求体中的数据绑定到方法参数,通常用于处理 POST 请求的 JSON
    数据。
  8. @Autowired: 自动装配依赖,可以用在构造函数、属性和方法上。
  9. @Value: 注入配置属性的值。
  10. @Component: 将类标记为 Spring 组件,使其可以被自动扫描并注册为 Bean。
  11. @Service, @Repository, @Controller: 用于标记类为服务层、数据访问层和控制器层的组
    件,与 @Component 功能类似,但可以提供更具体的语义。
  12. @Configuration: 声明一个类作为配置类,用于定义 Bean 和配置信息。
  13. @EnableAutoConfiguration: 启用自动配置,Spring Boot 根据依赖自动配置应用程序。
  14. @Conditional: 根据条件判断是否创建 Bean,例如 @ConditionalOnProperty 用于在满
    足某个属性条件时创建 Bean。
  15. @Profile: 定义 Bean 在特定环境下生效。
  16. @SpringBootTest: 用于在测试中加载 Spring Boot 应用程序上下文。
  17. @Test, @Before, @After: JUnit 测试相关的注解,用于定义测试方法、初始化方法和清理
    方法。
  18. @ConfigurationProperties: 用于绑定配置属性到 Java 类。
  19. @EnableCaching: 启用 Spring 缓存。
  20. @Scheduled: 用于定义定时任务。

这只是一小部分 Spring Boot 注解,还有许多其他注解用于不同的场景和功能。根据需要,你可以深入学习并应用这些注解来开发和配置 Spring Boot 应用程序。

第十七天

1. MySQL 的内连接、左连接、右连接有什么区别?

内连接关键字:inner join;左连接:left join;右连接:right
join。 内连接是把匹配的关联数据显示出来;左连接是左边的表全部显示
出来,右边的表显示 出符合条件的数据;右连接正好相反.

2.MySQL 索引是怎么实现的?

索引是满足某种特定查找算法的数据结构,而这些数据结构会以某种方式指向数据,从 而实现高效查找数据。

具体来说 MySQL 中的索引,不同的数据引擎实现有所不同,但目前主流的数据库引擎 的索引都是 B+ 树实现的,B+ 树的搜索效率,可以到达二分法的性能,找到数据区域之后 就找到了完整的数据结构了,所以索引的性能也是更好的。

3.索引的优点和缺点—查询频率高的字段

优势
1) 类似于书籍的目录索引,提高数据检索的效率,降低数据库的IO成本。
2) 通过索引列对数据进行排序,降低数据排序的成本,降低CPU的消耗。
劣势
1) 实际上索引也是一张表,该表中保存了主键与索引字段,并指向表的记录,所以索引列也是要占用空间的。
2) 虽然索引大大提高了查询效率,同时却也降低更新表的速度,如对表进行INSERT、UPDATE、DELETE。因为更新表时,MySQL 不仅要保存数据,还要保存一下索引文件每次更新添加了索引列的字段,都会调整因为更新所带来的键值变化后的索引信息。

4.B+树的特点和作用----必须先看下面的网址

https://mp.weixin.qq.com/s?__biz=MzIxMjE5MTE1Nw==&mid=2653190965&idx=1&sn=53f78fa037386f85531832cd5322d2a0&chksm=8c9909efbbee80f90512f0c36356c31cc74c388c46388dc2317d43c8f8597298f233ca9c29e9&scene=21#wechat_redirect

https://mp.weixin.qq.com/s?__biz=MzIxMjE5MTE1Nw==&mid=2653191027&idx=1&sn=4ba22e3ec8bd149f69fc0aba72e4347e&chksm=8c9909a9bbee80bfa1d8497ff0525df130414c1731b5aa5287bf16ea1cf86c8d8e6f20782184&scene=21#wechat_redirect

在这里插入图片描述

5. 什么是聚集索引和非聚集索引

在数据库的聚集索引(Clustered Index)中,叶子节点直接包含卫星数据。在非聚集索引(NonClustered Index)中,叶子节点带有指向卫星数据的指针。

6.索引的分类

1) 单值索引 :即一个索引只包含单个列,一个表可以有多个单列索引
2) 唯一索引 :索引列的值必须唯一,但允许有空值
3) 复合索引 :即一个索引包含多个列
4) 主键索引:

7.什么是最左前缀法则以及如何设计最左法则

MySQL中的索引可以以一定顺序引用多列,这种索引叫作联合索引。如User表的name和city加联合索引就是(name,city),而最左前缀原则指的是,如果查询的时候查询条件精确匹配索引的左边连续一列或几列,则此列就可以被用到。在创建联合索引时,索引字段的顺序需要考虑字段值去重之后的个数,较多的放前面

8. 怎么验证 MySQL 的索引是否满足需求?

使用 explain 查看 SQL 是如何执行查询语句的,从而分析你的索引是否满足需求。
explain 语法:explain select * from table where type=1。

9.说一下 MySQL 常用的引擎?

InnoDB支持事务, MyISAM不支持
InnoDB支持行级锁, MyISAM支持表级锁.
InnoDB支持外键, MyISAM不支持.
MyISAM支持全文索引, InnoDB不支持(但可以使用Sphinx插件)

10.MySQL由哪些部分组成, 分别用来做什么

在这里插入图片描述
1 连接器: 管理连接, 权限验证.
2 分析器: 词法分析, 语法分析.
3 优化器: 执行计划生成, 索引的选择.
4 执行器: 操作存储引擎, 返回执行结果.
5 存储引擎: 存储数据, 提供读写接口.

11.说说对 SQL 语句优化有哪些方法 [必须背会]

https://blog.csdn.net/biyusr/article/details/125599865

(1)Where 子句中:where 表之间的连接必须写在其他 Where 条件之前,那些可以过滤掉最大数量记录的条件必须写在 Where 子句的末
尾.HAVING 最后。
(2)用 EXISTS 替代 IN、用 NOT EXISTS 替代 NOT IN。
(3)对查询进行优化,应尽量避免全表扫描,首先应考虑在 where 及order by 涉及的列上建立索引。
(4)应尽量避免在 where 子句中对字段进行 null 值判断,否则将导致引擎放弃使用索引而进行全表扫描
(5)应尽量避免在 where 子句中对字段进行表达式操作,这将导致引擎放弃使用索引而进行全表扫描

12.说一下 MySQL 的行锁和表锁?

MyISAM 只支持表锁,InnoDB 支持表锁和行锁,默认为行锁。
表级锁:开销小,加锁快,不会出现死锁。锁定粒度大,发生锁冲突的概率最 高,并发量最低。

行级锁:开销大,加锁慢,会出现死锁。锁力度小,发生锁冲突的概率小,并 发度最高。

13.说一下乐观锁和悲观锁?

乐观锁:每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在提 交更新的时候会判断一下在此期间别人有没有去更新这个数据。
悲观锁:每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都 会上锁,这样别人想拿这个数据就会阻止,直到这个锁被释放。
数据库的乐观锁需要自己实现,在表里面添加一个 version 字段,每次修改成功值加 1,这样每次修改的时候先对比一下,自己拥有的 version 和数据库现在的 version 是否 一致,如果不一致就不修改,这样就实现了乐观锁。

14. MySQL 问题排查都有哪些手段?

开启慢查询日志,查看慢查询的 SQL。
使用 explain 命令查询 SQL 语句执行计划。

15.什么是存储过程?用什么来调用?

存储过程是一个预编译的 SQL 语句,优点是允许模块化的设计,就是说只需创建一次,以后在该程序中就可以调用多次。如果某次操作需要执行多次SQL,使用存储过程比单纯 SQL 语句执行要快。可以用一个命令call对象来调用存储过程。

第十八天

1. 创建对象的方式

  1. 实例化类(通过构造函数创建对象):
  2. 通过反射
  3. 通过克隆技术
  4. 通过反序列化

2. JDK8有哪些新特性

  1. Lambda表达式
  2. Stream API
  3. 接口的默认方法和静态方法
  4. 方法引用
  5. 新的日期和时间API

3. springcloud框架从发起请求之后,整个项目的流程

Spring Cloud是一个用于构建分布式系统的框架,它基于Spring Boot,提供了一套丰富的工具和组件来简化微服务架构的开发和管理。以下是在Spring Cloud中从发起请求到整个项目流程的简要概述:

  1. 发起请求: 客户端(例如Web浏览器或其他服务)发起HTTP请求到Spring Cloud服务的API网关或负载均衡器。在微服务架构中,通常会有多个服务实例提供相同的功能,负载均衡器可以将请求分发给可用的服务实例。
  2. 网关路由: 请求到达API网关后,网关根据配置的路由规则将请求路由到相应的微服务。路由规则可以根据请求的路径、参数等信息来匹配目标服务。
  3. 身份验证和授权: 在进入具体的微服务之前,Spring Cloud可以进行身份验证和授权操作。这可以通过集成Spring Security或其他安全框架来实现。
  4. 微服务处理: 请求到达目标微服务后,该微服务将处理请求,并根据业务逻辑进行相应的处理。在这个阶段,可能会涉及到数据库访问、业务计算、调用其他微服务等操作。
  5. 服务间通信: 在微服务架构中,不同的微服务之间可能会存在依赖关系。在处理请求时,一个微服务可能需要调用其他微服务来获取所需的数据或执行其他操作。Spring Cloud提供了各种方式来实现服务间通信,如Feign、Ribbon和RestTemplate。
  6. 熔断与降级: 在微服务架构中,不同的服务可能存在相互依赖,当某个服务出现故障或延迟时,可能会导致级联故障。Spring Cloud通过熔断器(例如Hystrix)来处理这种情况,当某个服务不可用时,可以进行快速的降级处理,以防止整个系统崩溃。
  7. 响应结果: 微服务处理完请求后,将结果返回给客户端。在返回之前,可以进行结果的封装、转换或其他处理。
  8. 服务注册与发现: 在Spring Cloud中,服务的注册与发现是一个重要的特性。各个微服务会将自己的信息注册到服务注册中心,以便其他微服务能够发现并调用它们。常用的服务注册与发现组件是Eureka或Consul。
  9. 监控与日志: 在生产环境中,对于微服务的健康状态和性能表现进行监控是必要的。Spring Cloud提供了一系列的监控和日志组件,如Spring Cloud Sleuth和Zipkin,来帮助开发人员对微服务进行跟踪和分析。
  10. 负载均衡和高可用性: Spring Cloud提供了负载均衡的支持,以确保请求被平均分布到多个服务实例上,从而实现高可用性和扩展性。

4. Stream流用的多吗?如何把list转换为map

蛮多的。使用Collectors.toMap()方法

import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

public class Main {
 public static void main(String[] args) {
     List<Person> personList = List.of(
         new Person("Alice", 30),
         new Person("Bob", 25),
         new Person("Charlie", 35)
     );

     // 将List<Person>转换为Map<String, Person>,以name属性作为key
     Map<String, Person> personMap = personList.stream()
         .collect(Collectors.toMap(Person::getName, person -> person));

     // 打印结果
     personMap.forEach((name, person) -> System.out.println(name + ": " + person));
 }
}

class Person {
 private String name;
 private int age;

 public Person(String name, int age) {
     this.name = name;
     this.age = age;
 }

 public String getName() {
     return name;
 }

 public int getAge() {
     return age;
 }
}

5. 说一下你是如何操作git

6. Mybatis或MybatisPlus底层分页实现原理?

Mybatis-Plus的底层分页实现原理是通过自定义拦截器来拦截执行的SQL语句,在查询SQL的基础上增加分页逻辑,同时执行额外的查询来获取总记录数,并将结果封装到Page对象中返回给应用层。这样,使用Mybatis-Plus提供的分页功能可以简化分页查询的操作,提高开发效率。

7. 什么是服务雪崩?如何解决

所谓的服务雪崩就是在微服务调用链路中,某个服务出现故障,而导致整个调用链路上服务出现故障。

解决方式: 1. 设置超时 2. 线程隔离 3. 限流 4. 熔断降级

而使用的组件: sentinel 或 hystrix

8. 什么是自动装箱和自动拆箱

自动装箱是指将基本数据类型转换为对应的包装类对象。 例如: 将int类型的变量赋值给Integer对象

自动拆箱是指将包装类对象转换为对应的基本数据类型 .例如: 将Integer对象赋值给int类型的变量:

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值