2025年4月15日 百度一面 面经 胡言乱语版
1. 代理相关 从静态代理到动态代理
对目标行为的一种增强 前增强 后增强
静态代理
接口 定义规则
实现了接口的具体类
代理类 代理类生成具体类对象
然后继承了代理类
重写方法
使用具体类对象调用方法 并且加上自己逻辑
我们只要使用代理类对象就能实现代理
动态代理分为 JDK 动态代理和 Cglib 动态代理
JDK 动态代理主要是利用了 Proxy 类里面的 newProxyInstance(不会读 说的新的代理单例) 方法获取代理单例
传入参数 类加载器 实现接口 代理对象自定义类
代理对象自定义类实现了一个叫调用处理的接口(InvocationHandler)
然后重写 invoke 方法
原理实际上是将方法传到了 InvocationHandler 的 invoke 方法里面去
之后重写逻辑即可
cglib 动态代理也是如同 jdk 动态代理一样 (这边没说) 首先用工厂模式创建一个 Factory
定义一个方法获取代理对象 传入 Object
然后创建增强对象
传入类加载器
代理类
拦截器
拦截器同样是实现接口 我们在里面重写方法(这边说累了 就没说 )
最后总结
JDK 动态代理使用较多 但是限制是只能代理接口类
最后又想了想 静态代理是编译的时候就进入机器的 可拓展性很差
动态代理允许在运行的时候动态编译... (忘了)
(答 太多 就虚了 疯狂遗忘+口误)
2. cglib可以代理被final修饰的类吗,为什么
cglib动态代理是原理靠继承实现的
相当于让父类继承子类 然后优先调用子类的方法
面试官说我答的很含糊 问我有没有看过源码
我讲了一下cglib 动态代理的流程
工厂模式创建一个 factory 对象 然后创建一个动态代理增强类 Enhancer 对象
通过增强类的 set 方法传入参数
第一个参数 利用反射得到的类加载器
第二个参数 被代理类
第三个参数 方法拦截器 使用的一个命名为回调方法的东西
最后返回这个 代理类对象的 create() 方法
其中这个方法拦截器 实现了 MethodInterceptor 接口
重写了 intercept 方法
添加了自己的操作 与 jdk 动态代理的 invoke 方法相似
面试官又问我如何体现继承的
我说我看过源码 方法拦截器是传到一个数组里面去了 我看不懂源码 (汗流浃背)
3. JVM 体系结构
只记得类加载器
讲了一会 巴拉巴拉 八股吟唱 啦啦啦
加载 连接 初始化 使用 卸载
连接又分为验证 准备 解析
还卡了好几下
让我别讲了
4. 垃圾回收算法
只记得名字叫 GC 还涉及什么代什么代
忘了 没看 (我简历上也没写 JVM 啊 难道是答动态代理的时候口误)
5. 什么是注解 如何使用 底层原理
不会
6. synchronized和reentrantlock
自带锁
JVM 提供的
为了保证锁的安全
在底层是用了内存屏障 ...
下面的忘了 寒假学的
7. 讲一下你项目中 redis的分布式锁 与java自带的锁有啥区别
redis 分布式锁适用于多机部署的分布式系统 多节点资源访问
比如说电商平台中多服务器同时扣商品库存
每次加锁释放锁都要与 redis 进行网络通信
适用于分布式场景
Java 自带的锁实现简单
8. post 请求和 get 请求的区别
GET请求数据编码后放在 url 里面 长度限制为几千
POST 请求数据放在请求体里面
get 请求 一次 tcp 握手 (只发送请求头)
post 请求两次 tcp 握手(因为要先发送 请求头 再发送请求体)
密码等安全性数据放在 POST 请求里面
get 请求能被服务器缓存
get 请求幂等 通常是获取
post 请求不幂等 通常是修改
9. IOC 和 AOP 的使用
这题我会
IOC bean 容器 讲了简单的 bean 容器 从 beanfactory 到 hashMAp
实际上 spring 源码中用了很复杂的设计模式
aop 基于动态代理实现
面向切面
10. 过滤器和拦截器
这题我会(语音输入)
过滤器跟拦截器是不同的,然后首先过滤器叫英文名叫Filter,它是在 Http 请求到达那个服务器后之后就面临的,它那个跟是是位于sevlet 和那个 web 服务器之间,所以它在到达sevlet服务器之前就已经到达过滤器了,你在过使用过滤器的时候是继承它那个 falter 接口,然后你可以通过它传入的request或者 reponse,然后进行一些操作,然后你重写了,你实现了这个接口后,然后你还需要让这个接口生效的话,你需要去再在这个外部林插庙这个注解里,或者说你打上注解也行。
过滤器其实sevlet 的方法都差不多,是按sevlet的规范来写的,然后过滤器它也是 有 init 方法, init 方法和这个doFilter,还有 destory(), 它这个函数说一定初始化,然后如果你要测试过滤器的功能,你可以在这个doFilter的里面去写一个输出网站名称那个打印一下,然后就把它塞到那个response里面去,然后你就会看到这个response里有response里,然后就会往下传,传的话进入到service,再往下,再往下再到control。
拦截器,它是位于sevlet跟control之间的,你可以在请求进来之前就对它进行一个拦截,然后它也是跟Filter差不多,也是传入通和那个request代表传入的请求和和那个返回的请求,然后再继续在传给control之前进行一个过滤。
11. 如果现在要写一个拦截器去拦截访问路径 你会怎么设计
拦截器实现的是 HandlerInterceptor 接口
重写方法
preHandle () 主要逻辑
首先排除白名单 然后从 HttpSession 里面拿登录信息 satoken 和 jwt 类似 然后判断返回
postHandle() 后处理
记录一下访问时间 往中间件里去写 对 resquest 和 response 进行修改
afterCompletion() 完成处理
写日志 类似的...
import HandlerInterceptor.HandlerInterceptor; import org.springframework.util.AntPathMatcher; import javax.servlet.http.*; public final class LoginInterceptor implements HandlerInterceptor { // 不需要拦截的路径 private static final String[] EXCLUDE_PATHS = { "/user/login", "/user/register", "/static/**", "/error" }; @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { String requestURI = request.getRequestURI(); // 1. 排除不需要拦截的路径 [8]() for (String path : EXCLUDE_PATHS) { if (new AntPathMatcher().match(path, requestURI)) { return true; } } // 2. 检查登录状态 [7]() HttpSession session = request.getSession(); Object userInfo = session.getAttribute("LOGIN_USER"); // 3. 当用户未登录时 if (userInfo == null) { // 根据请求类型返回不同响应 [3]() if (isAjaxRequest(request)) { response.setContentType("application/json"); response.getWriter().write("{\"code\":401, \"msg\":\"未认证\"}"); } else { response.sendRedirect("/login"); } return false; } // 4. 可扩展的权限验证逻辑 [15]() // 例如验证token有效期、权限级别等 return true; } // 后处理 @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler // ModelAndView modelAndView ) throws Exception { // 记录请求处理时间、修改响应头等 [10]() long startTime = (Long) request.getAttribute("requestStartTime"); long executeTime = System.currentTimeMillis() - startTime; request.setAttribute("executeTime", executeTime); } // 完成处理 @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { // 资源清理、异常记录等 [7]() if (ex != null) { // log.error("Request processing error: " + request.getRequestURI(), ex); } } // 判断是否为Ajax请求 private boolean isAjaxRequest(HttpServletRequest request) { return "XMLHttpRequest".equals(request.getHeader("X-Requested-With")); } }
12. redis 数据结构
讲了常见的 5 种
字符串 第二个项目存每次访问网站静态数据
哈希 第二个项目中存帖子点赞信息
列表
集合
有序集合
13. redis 哨兵以及他的优点
没看
14. 算法 力扣 7 整数翻转 中等题
**********************************************
错误结果用异常写的 面试官说我的方法很巧妙
class Solution { public int reverse(int x) { StringBuilder sb=new StringBuilder(""); String str=x+""; if(str.charAt(0)=='-'){ sb.append('-'); sb.append(new StringBuilder(str.substring(1,str.length())).reverse()); }else{ sb.append(new StringBuilder(str.substring(0,str.length())).reverse()); } try{ return Integer.parseInt(sb.toString()); }catch(Exception e){ return 0; } } }
总结
我记得我简历上没有写 JVM 相关的啊...
redis 哨兵那边忘了
总体而言 觉得有点过于简单了
Springboot -> Juc -> 中间件 -> 算法
问到代理相关可能是因为
然后往下我就写了并发相关的
并发编程那边寒假学了 JUC 还没复习
题目确实简单 晚上看了一下 但是答的还是很不满意的 再加上 27 届过得概率应该挺小的
想死啦 可能是这辈子第一个大厂 就被挂 凉
27届双非