面试记录二

20240410

  1. 如何理解Spring、Srping Boot 和 Spring Cloud

    • Spring

      非入侵式:业务代码中不会出现 Spring 的API ;容器:提供容器,管理 bean 的生命周期以及对象之间的关系;

      IOC:控制反转,是一种编程思想将对象的创建控制权交给容器控制;AOP:面向切面编程,提供将公共逻辑代码抽离封装的能力,实现代码的解耦和重用

    • Spring Boot

      相对于 Spring 而言简化的繁杂的配置工作,提高开发的效率。其设计理念是约定大于配置,所以提供了大量的starter 共给开发人员使用。同时内嵌了像 Tomcat,Jetty 等 sevelt 容器,简化了部署工作

    • Spring Cloud

      是基于 Spring Boot 的一套微服务架构,依赖与很多套件实现服务间通讯,服务发现、配置管理等,本身自己不提供实际功能。

  2. sql 怎么优化

    • 添加索引,explain 命令可以查看 SQL 的执行计划,key:实际用到的索引和 rows:预计检查的行数。
    • 不要使用 select *
    • 用 union all 替代 union :union会去重重排,排重的过程需要遍历、排序和比较,它更耗时,更消耗cpu资源
    • 使用小表驱动大表:in 适用于左边大表,右边小表。 exists 适用于左边小表,右边大表。
    • 尽量使用批量操作
    • 需要单条数据时使用 limit
    • in 中的值不要太多
    • 分页查询 : 考虑使用自增ID或者时间 提高查询效率
    • 用连接查询代替子查询: 子查询会创建临时表,查询结束后再删除增加额外的消耗
    • join 的表不易过多: left join 尽量左边要用小表,右边可以用大表。如果能用inner join的地方,尽量少用left join。
    • 控制索引的数量: 更新和删除操作都会更新索引,如果索引过多,会消耗很多额外的性能。能够建联合索引,就别建单个索引,可以删除无用的单个索引。
    • 使用where条件在分组前,就把多余的数据过滤掉
  3. 索引失效的原因

    • 数据类型不匹配:如果查询条件中的数据类型和索引列的数据类型不一致,会导致索引失效。因为 MySql 会进行隐式类型转换,这会使索引无法被有效使用。

    • 违反最左前缀原则:在使用联合索引时,查询条件必须遵循最左前缀原则,即从左到右依次使用联合索引中的列,不能跳过任何一列,否则索引会失效。

    • where 语句 索引列上进行了函数操作或运算:如果在查询条件中对索引列进行了函数操作或运算,如使用LOWER()函数等,会导致索引失效。

    • 使用LIKE进行模糊查询且查询条件以通配符开头:当使用LIKE进行模糊查询,并且查询条件以通配符(%)开头时,索引会失效。因为数据库无法确定索引列的起始位置,所以无法利用索引进行快速查找。

    • 索引列包含 NULL 值:如果索引列中包含 NULL 值,在查询条件中使用 IS NULL 或 IS NOT NULL 也会导致索引失效。因为MySQL 在建立索引时不会存储空值,所以无法通过索引来判断是否为空。

    • 查询条件中使用 OR 关键字:如果查询条件中使用了 OR 关键字,并且 OR 两边的条件涉及到不同的索引列,那么也会导致索引失效。因为 MySQL 无法同时使用多个索引来进行查询优化,所以只能选择全表扫描。

    • in使用不当:in 在结果集 大于30%的时候索引失效

    • select * : 会导致回表查询所以影响查询效率;同时增加查询分析器解析成本和无用字段增加网络 耗,尤其是 text 类型的字段

  4. 最左匹配原则

    联合索引(a,b,c),会从左左侧开始匹配。假如没有a 则不会走索引,遇到范围查询会停止匹配。

  5. 事务失效的场景

    • 没有被 public 修饰:在Spring源码中,如果目标方法不是public,则TransactionAttribute返回null,不支持事务
    • 方法被 final 修饰:因为spring事务底层是用了aop,用了jdk的动态代理或者cglb的动态代理,会帮我们生成代理类,在代理类中实现事务功能
    • 同一个类中调用
    • 异常被捕获没有抛出
    • 多线程异步调用
    • 未指定回滚异常:解默认的回滚异常类型是运行时异常
  6. Countdownlatch和CyclicBarrier ,多线程

  7. mybatis plus 分页实现原理,拦截器

  8. delete 影响索引吗

    会,删除和更新会更新索引

  9. redis 基本类型

    String、list、set、zset(有序集合)、hash、stream、Bit arrays(位集合)、HyperLogLog(是用来做基数统计的算法。用于估计一个set中元素数量的概率性的数据结构。)、Geospatial Indexes(地理空间索引)、Streams(流信息)

  10. bean的生命周期

    • 实例化:根据配置文件中 Bean 的定义,利用 Java Reflection 反射技术创建 Bean 的实例

    • 属性注入:注入对象依赖的属性值(或对象)

    • 处理各种 Aware 接口:Spring 会检测该 Bean 是否实现了 xxxAware 接口,通过 Aware 类型的接口,可以让 Spring 框架为当前 Bean 注入相对应的内容

      ​ 如果 Bean 实现 BeanNameAware 接口,会调用实现的 setBeanName(string beanid)方法,注入bean 的名字;
      ​ 如果 Bean 实现 BeanClassLoaderAware 接口,调用setBeanClassLoader()方法,注入 ClassLoader 对象的实例;
      ​ 如果 Bean 实现 BeanFactoryAware 接口,会调用它实现的 setBeanFactory() 方法,注入的是 spring 工厂;
      ​ 如果 Bean 实现 ApplicationContextAware 接口,会调用 setApplicationContext() 方法,注入 spring 上下文;

    • 执行 BeanPostProcessor 前置处理:如果想对 Bean 进行一些自定义的前置处理,那么可以让Bean实现了BeanPostProcessor接口,将会在该阶段调用postprocessbeforeinitialization(Object obj,string s)方法

    • 执行initializingBean初始化方法:如果Bean实现了initializingBean接口,执行afeterpropertiesset() 方法

      ​ 执行init-method自定义初始化方法:如果Bean在spring配置文件中配置了init-method属性,则会自动调用其配置的初 始化方法

    • 执行了Beanpostprocessor后置处理:如果这个Bean实现了Beanpostprocessor接口,将会调用postprocessafterinitialization(object obj,string s)方法,由于这个方法是在Bean初始化结束后调用

    • 执行DisposableBean销毁Bean:当Bean不再需要时,会经历清理阶段,如果Bean实现了DisposableBean这个接口,会调用其实现的destory()方法执行销毁

      ​ 执行destory-method自定义销毁方法:如果这个Bean的spring配置中配置了destory-method属性,会自动调用其配置 的自定义销毁方法。

  11. 如何理解面向对象

    • 定义

      就是将要完成的一件“大事”,分割出其中的一个一个“独立对象”,每个对象都有其自身的“特征信息”,和“行为动作/功能”

    • 对象组成

      方法和属性

    • 特点

      封装:将数据和操作封装在对象内部,只对外提供公共的访问方式,这样提高了安全性和可维护性

      继承:继承允许一个类(子类)继承另一个类(父类)的属性和方法,这样可以复用父类的代码,提高开发效率

      多态:一个类实例的相同方法在不同情形下有不同的表现形式,实现方式重载和重写

  12. Java 反射机制

    • 理解

      在程序运行过程中,能够获取某一个类的属性和方法,并能够调用某一个对象的方法

  13. redis使用场景

  14. AOP具体使用

  15. Lambda 表达式

    1
    2
    3
    (parameters) -> expression

    (parameters) ->{ statements; }

    parameters:表示参数,没有小括号也不可省略,expression 和 { statements; } 表示方法体。

    • 主要特性

      简洁、可并行、方法引用(允许使用 :: 关键字来传递方法或者构造函数引用)、变量捕获(引用外部变量,该变量默然拥有 final 属性不可改变)、函数式编程支持(允许将函数当作参数传递给方法,或者将函数作为返回值