安脉盛 软件后端开发实习面经

了解 AOP 的原理吗?

"AOP 的底层核心其实就是动态代理。

Spring 在 Bean 生命周期的后置处理阶段,会通过 BeanPostProcessor 判断当前 Bean 是否需要增强,比如有没有 @Transactional、切面类等。

如果发现需要增强,Spring 就不会直接返回原始 Bean,而是会基于动态代理生成一个代理对象,最后放入 Spring 容器。

后续业务调用的其实是代理对象,而不是原对象。

Spring AOP 主要有两种代理方式:

JDK 动态代理

如果 Bean 实现了接口,Spring 会基于 java.lang.reflect.Proxy 生成接口代理对象。
CGLIB 动态代理

如果 Bean 没有实现接口,Spring 会使用 CGLIB 生成当前类的子类,通过重写方法实现增强。

而真正调用目标方法时,本质还是通过反射完成的。

比如 JDK 动态代理底层会进入:

java 复制代码
InvocationHandler.invoke()

然后通过:

java 复制代码
method.invoke(target,args)

反射调用目标方法。

java 复制代码
业务代码调用方法
↓
实际调用的是代理对象的方法
↓
代理对象拦截请求
↓
进入 InvocationHandler.invoke()
↓
执行前置增强,比如开启事务/打印日志
↓
通过 method.invoke(target, args) 调用原始目标对象方法
↓
执行后置增强,比如提交事务/统计耗时
↓
如果异常,执行异常增强,比如回滚事务
↓
返回结果

数据库 SQL 优化是怎么做的?

这个前面的博客有讲具体如何去定位慢查询,大概就是数据库sql优化

MySQL 的索引有几种类型?

这个前面的博客有具体讲

索引使用的数据结构是什么?

这个前面的博客有具体讲

接口跟抽象类有什么区别?

接口:

  • 支持多实现
  • JDK8前只能有抽象方法,之后可以有default方法

抽象类:

  • 可以有成员变量
  • 可以有普通方法

Java 类只能继承一个抽象类,但可以实现多个接口

重载跟重写有什么区别?

重载:

  • 发生在同一个类中
  • 方法名相同
  • 参数不同
  • 返回类型可以不同
  • 编译期决定

重写:

  • 发生在父子类
  • 方法必须一样
  • 子类重新实现
  • 运行期动态绑定

final 关键字有什么作用?

final 可以修饰:

类、方法、变量

  • 修饰类:不能被继承
  • 修饰变量:值不能被修改,只能在初始化时候被定义
  • 如果修饰引用类型:不能重新指向,但对象内容可以改
  • 修饰方法:不能被重写

重写(Override)的底层原理

重写本质上是:JVM 的动态绑定

底层核心:虚方法表

JVM会为每个类维护虚方法表

方法名→ 实际方法地址

Animal 虚方法表

复制代码
speak() -> Animal.speak()

Dog 虚方法表

java 复制代码
speak() -> Dog.speak()

第一步

找到:

java 复制代码
a 实际引用对象Dog

第二步

找到:

复制代码
Dog 虚方法表

第三步

定位:

复制代码
speak()

对应的方法地址


第四步

执行:

复制代码
Dog.speak()

finally 关键字的作用是什么?

finally 一般用于:

复制代码
try-catch-finally

无论是否异常finally 都会执行

一般用于:

  • 关闭连接
  • 释放资源
  • 解锁

反射有哪些作用?

反射可以:

运行时动态获取:

  • 方法
  • 字段

并动态调用对应的方法

Spring 大量用了反射。

比如:

  • IOC
  • AOP
  • 注解解析

Java 怎么实现多线程编程?

  • 第一:继承 Thread。
  • 第二:实现 Runnable。
  • 第三:实现 Callable + Future
  • 第四:使用线程池创建线程

你实现过多线程相关功能吗?具体是什么?

1.我五子棋项目中,使用阻塞队列进行一个匹配机制的实现使用的多线程相关功能

2.我做过 RabbitMQ 异步消费、文档异步索引

定时任务用什么实现?

我项目里主要用:

复制代码
XXL-JOB

它支持:

  • 分布式调度
  • 失败重试
  • 日志监控

实现线程时如何保证线程安全?

1.使用synchronized/ReentrantLock

2.使用原子类(AtomicInteger这种)

3.使用volatile避免指令重排序和实现内存可见性

4.使用CAS这种轻量级锁机制

5.使用线程安全类,比如hashtable,ConcurrentMap

6.使用ThreadLocal保存每个线程的私有变量

Java 的集合有哪些?集合对应的底层数据结构是什么?

  • List
  • Set
  • Map
  • Queue

ArrayList:

复制代码
动态数组

LinkedList:

复制代码
双向链表

HashMap:

复制代码
数组 + 链表 + 红黑树

TreeMap:

复制代码
红黑树

内存里的堆跟栈有什么区别?

栈存:

  • 局部变量
  • 方法参数
  • 方法调用信息

线程私有,速度快,自动回收

堆:

  • 存对象实例,
  • 线程共享
  • GC 主要回收堆

JVM 内存主要分为哪几个区域?

java 复制代码
1. 程序计数器(记录当前线程执行到哪条字节码指令)
2. Java 虚拟机栈(存方法运行时的数据)
3. 本地方法栈(给 Native 方法服务)
4. 堆(存对象实例)
5. 方法区(存类相关信息)

线程跟进程有什么区别?

  • 进程是操作系统进行资源分配的最小单位,线程是资源调度的最小单位。
  • 一个进程可以包含多个线程,同一个进程中的线程会共享
  • 相比进程,线程创建和切换成本更低,通信也更方便。
相关推荐
sycmancia1 小时前
Qt——Qt中的事件处理(一)
开发语言·qt
Halo_tjn1 小时前
Java IO流文件操作
java·开发语言
折哥的程序人生 · 物流技术专研2 小时前
《Java 100 天进阶之路》第23篇:缓冲区数据结构 ByteBuffer
java·开发语言·数据结构·后端·面试·求职招聘
REDcker2 小时前
C++循环与编译器优化详解 别名不变量向量化与GCC Clang验证及perf实践
java·jvm·c++·c·clang·gcc
lsx2024062 小时前
Razor VB 循环
开发语言
csuzhucong2 小时前
c++版本特性
开发语言·c++
高斯林.神犇2 小时前
Idea中使用Git
java·ide·intellij-idea
超梦dasgg2 小时前
Spring Security 原理 + 生产环境认证授权实战
java·后端·spring
wand codemonkey2 小时前
【第五步+前后分离调】最后的联动调试--java+Vue3项目
java·开发语言·vue.js