1、compareable和compactor区别
Comparable:是类内部实现的接口(位于java.lang
包),通过实现compareTo()
方法定义对象的“自然排序规则
Compactor:是外部比较器(位于java.util
包),通过独立类实现compare()
方法,允许在不修改原类代码的情况下定义多种排序规则
排序逻辑:Comparable由类自身定义唯一排序规则,Compactor可以自定义多种排序规则
2、SpringIOC,什么是控制反转,什么是依赖注入?
IOC其实就是控制反转,依赖注入(DI)是SpringIOC的一种实现方式
IOC(Inversion of Control):IOC指将对象的创建和管理权交给Spring容器(如ApplicationContext
)统一控制。传统开发中,对象通过new
主动创建依赖,而IoC模式下,容器负责对象的生命周期和依赖关系
DI(Dependency Injection):是IoC的具体实现方式,指容器在运行时动态将依赖对象注入到目标组件中
依赖注入的两种实现方式:
- XML配置:通过
<bean>
标签定义对象及依赖关系。 - 注解:如
@Autowired
(按类型注入)、@Resource
(按名称注入)、@Component
等,简化配置
依赖注入的三种方式
构造方法注入
Setter方法注入
属性注入:@Autowired,@Resources
spring容器的核心作用
创建和管理bean、依赖注入、管理bean生命周期
SpringAOP是什么?特点是什么
Spring AOP(面向切面编程)是 Spring 框架的核心模块之一,通过动态代理技术将横切关注点(如日志记录、性能监控、事务管理、安全控制等)与业务代码解耦。
核心是:
切面(Aspect)
封装横切逻辑的模块化单元,通过@Aspect
注解定义。例如日志切面类中可包含记录方法执行时间的代码
连接点(JoinPoint)
程序执行过程中的可插入点,如方法调用、异常抛出等。Spring AOP仅支持方法级别的连接点
通知(Advice)
通知类型:
- 前置通知(@Before):在方法执行前触发(如权限校验)。
- 后置通知(@After):在方法执行后触发(如日志记录)。
- 环绕通知(@Around):包裹目标方法,可控制执行流程(如事务管理)。
- 异常通知(@AfterThrowing):在方法抛出异常时触发(如错误处理)。
- 返回通知(@AfterReturning):在方法正常返回后触发
优点:与业务代码解耦,提高代码复用性,代码灵活性提高
代理
静态代理
动态代理
JDK动态代理:需要实现至少一个接口,这个接口可以是任意接口,spring会扫描是否使用了接口,如果有接口就用JDK动态代理,运行时动态生成接口实现类,用代理去掉用实现类的方法
CGLIB动态代理:是一个外部的类库,支持去代理未实现接口的普通类
JDK动态代理与CGLIB在Spring中互补使用,前者适用于接口代理,后者覆盖无接口场景
3、BIO/NIO/AIO区别
同步:同步就是发起一个调用后,被调用者未处理完请求之前,调用者不返回
异步:异步就是发起一个调用后,但是被调用者并没有返回结果,此时调用者可以处理其他请求。
阻塞:阻塞就是发起一个请求,调用者一直等待请求结果返回,也就是当前线程会被挂起,无法从事其他任务,只有当条件就绪才能继续。
非阻塞:非阻塞就是发起一个请求,调用者不用一直等着结果返回,可以先去干其他事情。
-
BIO是同步阻塞I/O模型,它使用一个线程来处理一个请求,如果这个请求没有被处理完,这个线程就会一直等待,直到请求处理完成。
-
NIO是同步非阻塞I/O模型,它使用单个线程来处理多个请求,这些请求可以同时被这个线程处理,它通过轮询的方式来处理I/O请求,如果有I/O请求就处理,没有就继续轮询。这种模型适用于连接数较多但是连接时间短的情况
-
AIO是异步非阻塞I/O模型,这种模型不需要为每个请求创建一个线程,由操作系统内部的线程来处理I/O请求,同时它也具有非阻塞的特性,I/
O请求不会一直等待,而是异步执行。这种模型适用于连接数很多的情况
举个生活中简单的例子,你妈妈让你烧水,小时候你比较笨啊,在那里傻等着水开(同步阻塞)。等你稍微再长大一点,你知道每次烧水的空隙可以去干点其他事,然后只需要时不时来看看水开了没有(同步非阻塞)。后来,你们家用上了水开了会发出声音的壶,这样你就只需要听到响声后就知道水开了,在这期间你可以随便干自己的事情,壶响了你需要去倒水了(异步非阻塞)。
4、final 在 Java 中有什么作用?
-
final 修饰的类叫最终类,该类不能被继承。
-
final 修饰的方法不能被重写。
-
final 修饰的变量叫常量,常量必须初始化,初始化之后值就不能被修改。
5、Java中的容器都有哪些?
6、http和https区别
传输形式:http是明文传输的,https加密传输,采用对称加密和非对称加密结合的方式
传输协议:http基于TCP协议,而https基于SSL/TLS 协议
端口不同:http端口为80,https端口为443
证书:https需要证书认证,而http不需要证书
7、Array 和 ArrayList 有何区别
-
Array 可以存储基本数据类型和对象,ArrayList 只能存储对象。
-
Array 是指定固定大小的,而 ArrayList 大小是自动扩展的。
-
Array 内置方法没有 ArrayList 多,比如 addAll、removeAll、iteration 等方法只有 ArrayList 有。
8、哪里用到了对称加密和非对称加密?
对称加密:JWT生成token
非对称:https,阿里云效代码仓库
9、spring框架哪里用到了反射?
1、bean的实例化:Spring通过反射动态创建对象实例,无需硬编码new
操作
2、依赖注入:通过反射调用setter
方法或直接修改字段(如Field.set()
),将依赖对象注入目标Bean
3、Spring AOP利用反射生成代理对象
4、Spring MVC处理请求:Spring MVC通过反射解析@RequestMapping
标记的方法,动态匹配请求参数并执行目标方法
5、数据库访问:Spring JDBC通过反射将ResultSet
数据映射到实体类字段
10、SPU和SKU
SPU(Standard Product Unit)标准产品单元:指的是标准化的产品单位,通常是一个品牌下具有相同特征、属性的一类产品,例如,iPhone 13可以被认为是一个SPU,它包含了所有配置和版本的iPhone 13
SKU(Stock Keeping Unit)库存保有单位:是指库存管理中的最小可用单元,用于区分具体商品的种类。例如,不同颜色、不同内存大小的iPhone 13将被视作不同的SKU。
11、Spring Cache是什么的?
SpringCache是Spring提供的一个缓存框架
Spring Cache利用了AOP,实现了基于注解的缓存功能,保证了幂等性,简化代码,提高接口响应速度
Spring Cache不支持TTL的设置,但是可以加上一个#后面可以设置过期时间
12、flowable干嘛的?
简化审核流程的代码,将我们审核流程的代码与业务代码解耦,比如将我们采购单的审核流程通过flowable完成,这样哪怕审核条件变化也可以不用修改代码;
13、xxl-job在哪用到了
1、xxl-job定期扫描死信队列中堆积的消息,每天将死信队列中的消息钉钉推送
2、订单完成:超过20天的订单,xxl-job去扫描订单表里20天前状态为运输中的订单,去调用快递100接口查看这些订单的状态,如果快递的状态为签收则修改订单的状态为完成,如果订单状态还是运输中,就将这些订单推送到客服中心,走人工
3、商品中心第一次全量同步使用ES做个定时任务
4、秒杀系统,在活动开始前5分钟将商品预热到Redis中,原理是我们活动都有一个活动表和活动明细表,XXL-JOB每5分钟扫描一次活动表,用活动表的活动开始日期减去当前日期剩余的时间如果小于五分钟就将活动对应的商品预热到Redis中
5、ELK定期清除10天前的日志
14、聚合支付Jeepay
我们使用的聚合支付jeepay,只需要在Jeepay管理后台填入支付宝/微信等渠道的接口参数(如APPID、密钥),系统自动生成支付路由规则,通过Jeepay提供的Java SDK或HTTP接口,用一行代码发起支付请求,屏蔽不同支付平台的差异,支付结果通过MQ(如RabbitMQ)异步通知业务系统,需验签并更新订单状态,确保高可用。
15、如何设计一个秒杀系统
前端:
1、前端页面静态化+CDN,意思是对于秒杀活动设计来说,我们可以将所有可以静态化的内容全部静态化,然后将其配置在 CDN 服务器上。这样既提高了用户打开页面的时间,又减少了后端服务器的压力。
2、请求频率限制进行优化
后端:
-
增加缓存层 + 预热数据:我们在秒杀活动开始之前,可以手动将热点数据加载到缓存中,从而避免秒杀时去请求数据库
-
MQ 异步处理:
-
限流、熔断、降级
-
业务端优化
16、为什么要序列化和反序列化?
为了能将数据持久化存储,网络传输,跨语言支持,提高效率
其核心作用在于实现数据结构的跨场景兼容性
例如:
网络传输:网络通信只能传输二进制字节流,而程序中的对象无法直接传输。序列化将对象转换为字节流(如JSON、二进制等),接收方再通过反序列化还原为对象,实现跨网络的对象传递
持久化存储:对象无法直接存储到文件或数据库,需序列化为特定格式(如二进制、XML)
序列化和反序列化是连接内存对象与外部介质(网络、存储)的桥梁,解决了数据跨场景交互、持久化和跨语言协作的难题。合理使用可提升系统扩展性,但需注意版本控制、安全性和性能优化。
17、JWT好处
无状态
有效避免CSRF攻击
适合移动后端
单点登录友好
18、线程池核心参数怎么设置
CPU密集型:核心线程数=CPU核数,最大线程数=核心线程数
IO密集型任务:核心线程数=CPU核数x2,最大线程数=根据阻塞系数计算
阻塞系数0~1,阻塞系数越大,CPU越闲,一般阻塞系数为0.8
19、你对工作的期望是什么?
1、我希望通过我的努力,为团队和公司解决实际问题,推动项目的成功落地。同时,我也非常期待能够在团队中与优秀的同事合作,共同成长。
2、我对工作的期望是能够在公司中深入参与到具体技术领域,如分布式系统、大数据处理等相关的项目中。我希望通过实践不断提升自己的技术水平,并将所学应用于实际场景,为公司创造更多价值。
此外,我也期待能够在一个鼓励创新和持续学习的环境中工作,与团队一起攻克技术难题。
20、你自己感觉你是一个怎样的人?
1.好学 2.责任心强 3,协作强 4.吃苦耐劳 5.自我总结自我复盘 6.积极上进
21、你如何去胜任这份工作?
1.多年经验 2.高效的编码能力 3.全栈 4.沟通能力强 5.及时汇报进度
6.自我学习,解决问题 7.同学在这个领域,经常沟通学习
22、你们人脸识别传的核心参数有哪些?
性别,年龄,业主的某一帧的照片
23、享元模式
是一种结构型设计模式,其核心思想是通过共享技术减少大量相似对象的资源消耗,优化内存使用和系统性能。
优点:减少内存占用:通过共享对象避免重复创建;提升性能:降低对象频繁创建/销毁的开销
缺点:增加系统复杂性以及线程安全问题
场景:字符串常量池、数据库连接池、游戏开发(角色与道具复用
)
24、单体数据库挂了怎么保证数据的可靠性?
日志持久化、数据备份与恢复、主从复制、最好采用集群
25、MySQL的二阶段提交
第一阶段先把数据提交的内存和redolog中,二阶段后台起一个线程去将redolog日志里记录的数据刷新到磁盘里
26、list、set、map区别
特性 | List | Set | Map |
---|---|---|---|
重复元素 | 允许 | 不允许 | 键唯一,值可重复 |
Null 值 | 允许多个 null | 最多一个 null(如 HashSet 允许,TreeSet 不允许) |
键最多一个 null,值允许多个 null |
顺序性 | 按插入顺序存储 | 默认无序(TreeSet 有序,LinkedHashSet 按插入顺序) |
默认无序(TreeMap 按键排序,LinkedHashMap 按插入顺序) |
27、实现深拷贝的两种核心方式
1、实现 Cloneable
接口 + 重写 clone()
方法
①目标类实现 Cloneable
接口(标记接口,无方法需实现
②重写 Object
类的 clone()
方法,所有需要深拷贝的引用类型属性所在的类,都必须实现 Cloneable
接口并重写 clone()
方法,否则仅实现浅拷贝
2、序列化(Serializable
接口)
目标类实现 Serializable
接口
通过对象序列化与反序列化生成新对象,自动实现深拷贝
28、死锁产生的条件
互斥条件(锁的互斥):一个资源一次只能被线程持有
保持条件:一个线程获取资源时,会一直持有这些资源,直到获取所有满足的资源才释放
不剥夺条件:已分配的资源不能被其他线程抢走
环路等待:多个线程形成一种循环等待的关系,互相持有对方所需资源,导致死锁
死锁产生这四个条件必须全部满足,少一个都产生不了死锁
如何避免死锁?
1. 尽量避免使用多个锁,尽量使用一个锁。
2.减少锁的粒度, 确保同步代码块的执行时间尽可能短,这样可以减少线程等待时间,从而避免死锁的产生。
3. 使用尝试锁,通过 ReentrantLock.tryLock() 方法可以尝试获取锁,如果在规定时间内获取不到锁,则放弃锁。
4. 避免嵌套锁,如果需要使用多个锁,请确保它们的获取顺序是一致的,这样可以避免死锁。
29、static 属性为什么不会被序列化
因为序列化是针对对象而言的, 而 static 属性优先于对象存在, 随着类的加载而加载, 所以不会被序列化.
static修饰的类的,而我们序列化是针对对象的
30、强软弱虚引用
强引用:普通的变量引用
软引用:
-
当所剩内存空间不够我们新的对象存储的时候,直接干掉软引用。
-
当所剩内存空间够我们新对象的存储的时候,不会删除我们的软引用对象。
弱引用:将对象用WeakReference弱引用类型的对象包裹,弱引用跟没引用差不多,GC会直接回收掉,只要GC执行了,他就会被回收掉.
虚引用:虚引用也称为幽灵引用或者幻影引用,它是最弱的一种引用关系,几乎不用
31、你们接到一个新项目怎么做的?
开需求发布会
技术栈选型
分组开发
核心的接口讨论一下,定义一下入参出参
建代码仓库,接下来每个人去实现自己功能
项目快完成的时候联调测试一下
测试完没问题就上线
上线后跟踪
32、你最近遇到的技术难点?
1、库存的派生列(过期时间)
2、springcloud使用openfeign的时候,当我们使用GetMappering传递的参数是一个对象的时候,需要加一个注解,@springquerymap,否则他会默认将请求当做post请求
3、openfeign的解码器
4、乱脚本进行扣库存