3.26 面试复盘

160 阅读5分钟

1. nacos zookeeper eureka 的区别.

项目中用到了nacos, 当时没想到,这题目应该问的是分布式的 CAP理论

C: 分区一致性

A: 分区可用性

P: 分区容错性

eurekazookeepernacosconsul
APCPCP/APCP

2. MySQL 优化

  • 设计数据库时: 数据库表,字段的设计,存储引擎
  • 利用好MySQL自身提供的功能,如索引等
  • 横向扩展:MySQL集群、负载均衡、读写分离
  • SQL语句的优化(收效甚微)

3. 索引的类型

  1. 一般索引
  2. 主键索引
  3. 唯一索引
  4. 组合索引
  5. 全文索引

4. 多条件搜索页面怎么建立索引

  统计查询条件的离散程度 (distinct),按照最左原则将离散程度最大的放置在左侧.

5. 事务的特性

  • 原子性: 要么全都执行,要么全都没执行.
  • 一致性: 保证从一个正确的状态向另一个正确的状态迁移.(程序保证)
  • 隔离性: 多个并发操作对各个事务之间应该不能造成影响.
  • 持久性: 一个事务一旦提交,那就不能被回滚,在数据库中保存留档.

6. spring bean 的创建流程

  1. BeanDefinition解析: 调用容器中InstantiationAwareBeanPostProcessor的postProcessBeforeInstantiation()方法,可以在Bean实例化前修改BeanDefinition.
  2. 实例化: 将指定的BeanDefinition转换成BeanWrapper,然后调用createBeanInstance创建Bean的实例.Bean的实例化有多种策略,如工厂方法,指定参数构造器和默认无参构造器等.总之,createBeanInstance()方法会返回一个刚实例化好的,属性未赋值的空Bean.
  3. 属性填充: 调用populateBean()方法,为Bean进行属性的赋值和依赖的注入.
  4. 属性填充后置处理: 调用容器中InstantiationAwareBeanPostProcessor的postProcessAfterInstantiation()方法,进行属性填充后处理.
  5. 初始化前置处理: 调用BeanPostProcessor的postProcessBeforeInitialization()方法进行初始化前置处理.
  6. 初始化: 调用Bean的初始化方法,顺序为:InitializingBean的afterPropertiesSet() -> 注册的init-method.
  7. 初始化后置处理: 调用BeanPostProcessor的postProcessAfterInitialization()执行初始化后置处理.
  8. 调用registerDisposableBeanIfNecessary()方法,注册Bean的销毁处理逻辑: 将所有实现了DisposableBean接口的或者注册了destroy-method方法的Bean,封装成一个DisposableBean,将其销毁的回调注册到容器中.

7. ApplicationContext 继承了哪些接口

  1. EnviromentCapable: 所有Spring应用程序上下文都具有 EnvironmentCapable 功能,并且该接口主要用于在接受 BeanFactory 实例的框架方法中执行 instanceof 检查,以便可以与环境交互(如果确实可用),而 BeanFactory 实例实际上可以是ApplicationContext实例,也可以不是.
  2. MessageSource: 处理消息的策略接口,用户消息的参数化和国际化.
  3. ApplicationEventPulisher: 封装事件发布功能的接口.
  4. ResourcePatternResolver: 将位置模式解析成 Resource 对象的策略接口.
  5. ListableBeanFactory: BeanFactory 可以由哪些枚举出他们所有 bean 实例的 bean 工厂实现,而不是根据客户端尝试一个个查找.那些预加载所有 bean 定义的 BeanFactory 可以实现这个接口.
  6. HierarchicalBeanFactory: 由 bean 工厂实现的子接口, 可以是层次结构的一部分.可以在ConfigurableBeanFactory接口中找到用于bean工厂的相应setParentBeanFactory方法,该方法允许以可配置的方式设置父对象.

8. 线程池有哪些参数,是怎么运行任务的

  • corePoolSize: 核心线程数.
  • maximumPoolSize: 最大线程数.
  • threadFactory: 线程工厂,提供线程.
  • blockingQueue: 阻塞队列,缓存任务.
  • keepAliveTime: 线程空闲回收的时间.
  • rejectedExecutionHandler: 任务饱和后的拒绝策略.
  1. 提交任务进线程池.
  2. 线程池创建线程,直到达到核心线程数(corePoolSize),然后任务会进入阻塞队列(blockingQueue).
  3. 当阻塞队列达到最大值时,将会继续创建线程到最大线程数(maximumPoolSize).
  4. 当线程数达到最大线程数时,继续提交任务,会触发拒绝策略(rejectedExecutionHandler)
  5. 当有线程达到空闲时间(keepAliveTime),则会被回收.

9. 内置的拒绝策略有哪些

  1. RejectHandler: 默认的拒绝策略, 直接抛出拒绝异常.
  2. CallerRunsPolicy: 将任务交还由 execute 方法执行的线程去执行.
  3. DiscardOldestPolicy: 将阻塞队列中最早的任务丢弃.
  4. DiscardPolicy: 直接放弃提交进的任务
  5. AbortPolicy: 抛出带有详细信息的异常.

10. 如何选择拒绝策略

  对于必须不能放弃的任务来说,可以选择 CallerRunsPolicy 或者说自定义一个策略, 提交进新的线程池进去执行. 而不重要的业务可以根据不同的选择不同的丢弃策略.

11. 了解动态代理吗, 有哪些, Spring 默认用的是什么

  程序可以在运行期间生成代理对象,进行业务增强.

  JDK 默认的动态代理,以及 CGLIB 的代理增强.

  • Spring 5.x 中 AOP 默认依旧使用 JDK 动态代理.
  • SpringBoot 2.x 开始,为了解决使用 JDK 动态代理可能导致的类型转化异常而默认使用 CGLIB.
  • SpringBoot 2.x 中,如果需要默认使用 JDK 动态代理可以通过配置项 spring.aop.proxy-target-class=false 来进行修改,proxyTargetClass 配置已无效.

12. 了解静态代理吗

  静态代理需要在编码阶段,指定实际执行对象.实际行为将由代理类和被代理类同时控制.

13. CGLIB 和 JDK 的动态代理有什么区别

  1. CGLIB 的动态代理是基于可以不定义接口就实现动态代理,但是被代理对象,以及方法不能是被 final 修饰.
  2. JDK 的动态代理是基于反射, 但是被代理对象必须实现目标接口.

14. jdk 的动态代理是只要类实现接口就可以代理吗

  是的

15. git 不同的分支怎么合并

git merge 具体没有操作过,抽空去了解一下 git 的版本控制.

16. 版本怎么发布

  一般用流水线,Jenkins之类. 平时涉及的也很少.