面试记录二
20240410
如何理解Spring、Srping Boot 和 Spring Cloud
Spring
非入侵式:业务代码中不会出现 Spring 的API ;容器:提供容器,管理 bean 的生命周期以及对象之间的关系;
IOC:控制反转,是一种编程思想将对象的创建控制权交给容器控制;AOP:面向切面编程,提供将公共逻辑代码抽离封装的能力,实现代码的解耦和重用
Spring Boot
相对于 Spring 而言简化的繁杂的配置工作,提高开发的效率。其设计理念是约定大于配置,所以提供了大量的starter 共给开发人员使用。同时内嵌了像 Tomcat,Jetty 等 sevelt 容器,简化了部署工作
Spring Cloud
是基于 Spring Boot 的一套微服务架构,依赖与很多套件实现服务间通讯,服务发现、配置管理等,本身自己不提供实际功能。
sql 怎么优化
- 添加索引,explain 命令可以查看 SQL 的执行计划,key:实际用到的索引和 rows:预计检查的行数。
- 不要使用 select *
- 用 union all 替代 union :union会去重重排,排重的过程需要遍历、排序和比较,它更耗时,更消耗cpu资源
- 使用小表驱动大表:in 适用于左边大表,右边小表。 exists 适用于左边小表,右边大表。
- 尽量使用批量操作
- 需要单条数据时使用 limit
- in 中的值不要太多
- 分页查询 : 考虑使用自增ID或者时间 提高查询效率
- 用连接查询代替子查询: 子查询会创建临时表,查询结束后再删除增加额外的消耗
- join 的表不易过多: left join 尽量左边要用小表,右边可以用大表。如果能用inner join的地方,尽量少用left join。
- 控制索引的数量: 更新和删除操作都会更新索引,如果索引过多,会消耗很多额外的性能。能够建联合索引,就别建单个索引,可以删除无用的单个索引。
- 使用where条件在分组前,就把多余的数据过滤掉
索引失效的原因
数据类型不匹配:如果查询条件中的数据类型和索引列的数据类型不一致,会导致索引失效。因为 MySql 会进行隐式类型转换,这会使索引无法被有效使用。
违反最左前缀原则:在使用联合索引时,查询条件必须遵循最左前缀原则,即从左到右依次使用联合索引中的列,不能跳过任何一列,否则索引会失效。
where 语句 索引列上进行了函数操作或运算:如果在查询条件中对索引列进行了函数操作或运算,如使用LOWER()函数等,会导致索引失效。
使用LIKE进行模糊查询且查询条件以通配符开头:当使用LIKE进行模糊查询,并且查询条件以通配符(%)开头时,索引会失效。因为数据库无法确定索引列的起始位置,所以无法利用索引进行快速查找。
索引列包含 NULL 值:如果索引列中包含 NULL 值,在查询条件中使用 IS NULL 或 IS NOT NULL 也会导致索引失效。因为MySQL 在建立索引时不会存储空值,所以无法通过索引来判断是否为空。
查询条件中使用 OR 关键字:如果查询条件中使用了 OR 关键字,并且 OR 两边的条件涉及到不同的索引列,那么也会导致索引失效。因为 MySQL 无法同时使用多个索引来进行查询优化,所以只能选择全表扫描。
in使用不当:in 在结果集 大于30%的时候索引失效
select * : 会导致回表查询所以影响查询效率;同时增加查询分析器解析成本和无用字段增加网络 耗,尤其是 text 类型的字段
最左匹配原则
联合索引(a,b,c),会从左左侧开始匹配。假如没有a 则不会走索引,遇到范围查询会停止匹配。
事务失效的场景
- 没有被 public 修饰:在Spring源码中,如果目标方法不是public,则TransactionAttribute返回null,不支持事务
- 方法被 final 修饰:因为spring事务底层是用了aop,用了jdk的动态代理或者cglb的动态代理,会帮我们生成代理类,在代理类中实现事务功能
- 同一个类中调用
- 异常被捕获没有抛出
- 多线程异步调用
- 未指定回滚异常:解默认的回滚异常类型是运行时异常
Countdownlatch和CyclicBarrier ,多线程
mybatis plus 分页实现原理,拦截器
delete 影响索引吗
会,删除和更新会更新索引
redis 基本类型
String、list、set、zset(有序集合)、hash、stream、Bit arrays(位集合)、HyperLogLog(是用来做基数统计的算法。用于估计一个set中元素数量的概率性的数据结构。)、Geospatial Indexes(地理空间索引)、Streams(流信息)
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属性,会自动调用其配置 的自定义销毁方法。
如何理解面向对象
定义
就是将要完成的一件“大事”,分割出其中的一个一个“独立对象”,每个对象都有其自身的“特征信息”,和“行为动作/功能”
对象组成
方法和属性
特点
封装:将数据和操作封装在对象内部,只对外提供公共的访问方式,这样提高了安全性和可维护性
继承:继承允许一个类(子类)继承另一个类(父类)的属性和方法,这样可以复用父类的代码,提高开发效率
多态:一个类实例的相同方法在不同情形下有不同的表现形式,实现方式重载和重写
Java 反射机制
理解
在程序运行过程中,能够获取某一个类的属性和方法,并能够调用某一个对象的方法
redis使用场景
AOP具体使用
Lambda 表达式
1
2
3(parameters) -> expression
或
(parameters) ->{ statements; }parameters:表示参数,没有小括号也不可省略,expression 和 { statements; } 表示方法体。
主要特性
简洁、可并行、方法引用(允许使用
::关键字来传递方法或者构造函数引用)、变量捕获(引用外部变量,该变量默然拥有 final 属性不可改变)、函数式编程支持(允许将函数当作参数传递给方法,或者将函数作为返回值