阿里面试:看过框架源码吗?举例说明一下

简介: 阿里面试:看过框架源码吗?举例说明一下

前两天有朋友面试“淘汰集团”,也就是“淘宝”+“天猫”的组合,最后被面试官问到了这道题:“你看过哪些开源框架的源码?举例说明一下”。

诚然,这是一道比较考验应聘者基本功的问题,也是很好区分“好学生”和“普通学生”的一道经典的开放性问题。

那这个问题应该怎么回答呢?

解答思路

我这给大家提供两个思路吧:

  1. 可以回答比较常见的,你比较熟悉的源码,例如 Spring Boot 收到请求之后,执行流程的源码。
  2. 还可以回答 Spring Cloud 微服务中,某个组件执行的流程源码,这样能很好的体现你对微服务比较熟悉,因为微服务在公司中应用比较广泛,所以回答的好,是一个极大的加分项。

1.Spring Boot 源码分析

Spring Boot 在收到请求之后,会先执行前端控制器 DispatcherServlet,并调用其父类 FrameworkServlet 中的 service 方法,其核心源码如下:

/**
 * Override the parent class implementation in order to intercept PATCH requests.
 */
@Override
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
   

    HttpMethod httpMethod = HttpMethod.resolve(request.getMethod());
    if (httpMethod == HttpMethod.PATCH || httpMethod == null) {
   
        processRequest(request, response);
    } else {
   
        super.service(request, response);
    }
}

继续往下看,processRequest 实现源码如下:

protected final void processRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
   
 // 省略一堆初始化配置

   try {
   
       // 真正执行逻辑的方法
       doService(request, response);
   }
   catch (ServletException | IOException ex) {
   
       ...
   }
}

doService 实现源码如下:

protected abstract void doService(HttpServletRequest request, HttpServletResponse response) throws Exception;

doService 是抽象方法,由其之类 DispatcherServlet 来重写实现,其核心源码如下:

@Override
protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception {
   
    // 省略初始化过程...
    try {
   
        doDispatch(request, response);
    }
    finally {
   
        // 省略其他...
    }
}

此时就进入到了 DispatcherServlet 中的 doDispatch 方法了:

protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
   
    // 获取原生请求
    HttpServletRequest processedRequest = request;
    // 获取Handler执行链
    HandlerExecutionChain mappedHandler = null;
    // 是否为文件上传请求, 默认为false
    boolean multipartRequestParsed = false;
    WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
    try {
   
        ModelAndView mv = null;
        Exception dispatchException = null;
        try {
   
            // 检查是否为文件上传请求
            processedRequest = checkMultipart(request);
            multipartRequestParsed = (processedRequest != request);
            // Determine handler for the current request.
            // 获取能处理此请求的Handler
            mappedHandler = getHandler(processedRequest);
            if (mappedHandler == null) {
   
                noHandlerFound(processedRequest, response);
                return;
            }
            // Determine handler adapter for the current request.
            // 获取适配器
            HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
            // Process last-modified header, if supported by the handler.
            String method = request.getMethod();
            boolean isGet = "GET".equals(method);
            if (isGet || "HEAD".equals(method)) {
   
                long lastModified = ha.getLastModified(request, mappedHandler.getHandler());
                if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {
   
                    return;
                }
            }
            // 执行拦截器(链)的前置处理
            if (!mappedHandler.applyPreHandle(processedRequest, response)) {
   
                return;
            }
            // 真正的执行对应方法
            mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
            if (asyncManager.isConcurrentHandlingStarted()) {
   
                return;
            }
            applyDefaultViewName(processedRequest, mv);
            mappedHandler.applyPostHandle(processedRequest, response, mv);
        }
        // 忽略其他...
}

通过上述的源码我们可以看到,请求的核心代码都在 doDispatch 中,他里面包含的主要执行流程有以下这些:

  1. 调用 HandlerExecutionChain 获取处理器:DispatcherServlet 首先调用 getHandler 方法,通过 HandlerMapping 获取请求对应的 HandlerExecutionChain 对象,包含了处理器方法和拦截器列表。
  2. 调用 HandlerAdapter 执行处理器方法:DispatcherServlet 使用 HandlerAdapter 来执行处理器方法。根据 HandlerExecutionChain 中的处理器方法类型不同,选择对应的 HandlerAdapter 进行处理。常用的适配器有 RequestMappingHandlerAdapter 和 HttpRequestHandlerAdapter。
  3. 解析请求参数:DispatcherServlet 调用 HandlerAdapter 的 handle 方法,解析请求参数,并将解析后的参数传递给处理器方法执行。
  4. 调用处理器方法:DispatcherServlet 通过反射机制调用处理器方法,执行业务逻辑。
  5. 处理拦截器:在调用处理器方法前后,DispatcherServlet 会调用拦截器的 preHandle 和 postHandle方法进行相应的处理。
  6. 渲染视图:处理器方法执行完成后,DispatcherServlet 会通过 ViewResolver 解析视图名称,找到对应的 View 对象,并将模型数据传递给 View 进行渲染。
  7. 生成响应:View 会将渲染后的视图内容生成响应数据。

    2.Spring Cloud 源码

    Spring Cloud 组件有很多,你可以挑一个源码实现比较简单的组件来讲,这里推荐 Spring Cloud LoadBalancer,因为其核心源码的实现比较简单。

Spring Cloud LoadBalancer 中内置了两种负载均衡策略:

  1. 轮询负载均衡策略
  2. 随机负载均衡策略

轮询负载均衡策略的核心实现源码如下:

// ++i 去负数,得到一个正数值
int pos = this.position.incrementAndGet() & Integer.MAX_VALUE;
// 正数值和服务实例个数取余 -> 实现轮询
ServiceInstance instance = (ServiceInstance)instances.get(pos % instances.size());
// 将实例返回给调用者
return new DefaultResponse(instance);

随机负载均衡策略的核心实现源码如下:

// 通过 ThreadLocalRandom 获取一个随机数,最大值为服务实例的个数
int index = ThreadLocalRandom.current().nextInt(instances.size());
// 得到实例
ServiceInstance instance = (ServiceInstance)instances.get(index);
// 返回
return new DefaultResponse(instance);

小结

开源框架的源码在面试中经常会被问到,但只因如此,就去完整的看某个框架的源码,其实还是挺难的。第一,框架中的源码很多,很难一次性看懂。第二,即使能看懂,看完之后也会很快忘记(因为内容太多了)。此时,不如挑一些框架中的经典实现源码来看,其性价比更高,既能学到框架中的精髓,又能搞定面试,是一个不错的选择。

本文已收录到我的面试小站 www.javacn.site,其中包含的内容有:Redis、JVM、并发、并发、MySQL、Spring、Spring MVC、Spring Boot、Spring Cloud、MyBatis、设计模式、消息队列等模块。

相关文章
|
19天前
|
存储 安全 Java
面试题:用过ThreadLocal吗?ThreadLocal是在哪个包下的?看过ThreadLocal源码吗?讲一下ThreadLocal的get和put是怎么实现的?
字节面试题:用过ThreadLocal吗?ThreadLocal是在哪个包下的?看过ThreadLocal源码吗?讲一下ThreadLocal的get和put是怎么实现的?
32 0
|
7天前
|
API 数据库 数据安全/隐私保护
Flask框架在Python面试中的应用与实战
【4月更文挑战第18天】Django REST framework (DRF) 是用于构建Web API的强力工具,尤其适合Django应用。本文深入讨论DRF面试常见问题,包括视图、序列化、路由、权限控制、分页过滤排序及错误处理。同时,强调了易错点如序列化器验证、权限认证配置、API版本管理、性能优化和响应格式统一,并提供实战代码示例。了解这些知识点有助于在Python面试中展现优秀的Web服务开发能力。
22 1
|
4天前
|
Java 调度
Java面试必考题之线程的生命周期,结合源码,透彻讲解!
Java面试必考题之线程的生命周期,结合源码,透彻讲解!
32 1
|
7天前
|
SQL 中间件 API
Flask框架在Python面试中的应用与实战
【4月更文挑战第18天】**Flask是Python的轻量级Web框架,以其简洁API和强大扩展性受欢迎。本文深入探讨了面试中关于Flask的常见问题,包括路由、Jinja2模板、数据库操作、中间件和错误处理。同时,提到了易错点,如路由冲突、模板安全、SQL注入,以及请求上下文管理。通过实例代码展示了如何创建和管理数据库、使用表单以及处理请求。掌握这些知识将有助于在面试中展现Flask技能。**
12 1
Flask框架在Python面试中的应用与实战
|
16天前
|
机器学习/深度学习 分布式计算 BI
Flink实时流处理框架原理与应用:面试经验与必备知识点解析
【4月更文挑战第9天】本文详尽探讨了Flink实时流处理框架的原理,包括运行时架构、数据流模型、状态管理和容错机制、资源调度与优化以及与外部系统的集成。此外,还介绍了Flink在实时数据管道、分析、数仓与BI、机器学习等领域的应用实践。同时,文章提供了面试经验与常见问题解析,如Flink与其他系统的对比、实际项目挑战及解决方案,并展望了Flink的未来发展趋势。附带Java DataStream API代码样例,为学习和面试准备提供了实用素材。
39 0
|
1月前
|
存储 缓存 Java
什么!?实战项目竟然撞到阿里面试的原题!???关于MyBatis Plus的缓存机制
什么!?实战项目竟然撞到阿里面试的原题!???关于MyBatis Plus的缓存机制
|
1月前
|
存储 算法
【数据结构与算法】【腾讯阿里链表面试题】算法题--链表易懂版讲解
【数据结构与算法】【腾讯阿里链表面试题】算法题--链表易懂版讲解
|
2月前
|
缓存 监控 架构师
阿里面试:Java开发中,应如何避免OOM
在Java开发中,OutOfMemoryError(OOM)错误一直是令开发者头疼的问题,也是Java面试中出现核心频率很高的问题。 那么我们究竟怎么样才能够有效正确的管理内存,日常开发中究竟要注意哪些核心技巧来避免OOM错误。 本文将带大家一起学习10个避免OOM的实用小技巧,让大家在工作中能够有的放矢,避免OOM错误的飞来横祸。
53 1
|
3月前
|
算法 Java 程序员
阿里P8大佬终于把春招面试必备的神级Java面试手册给开源了!
先说说Java Java 作为国人编程开发语言中的 NO.1,已经占比半壁江山,选择入行做 IT 做编程开发的人,基本都把它作为首选语言,进大厂拿高薪也是大多数小伙伴们的梦想。 以前Java 岗位人才的空缺,而需求量又大,所以这种人才供不应求的现状,就是 Java 工程师的薪资待遇相对优厚的原因所在。 但是随着这个从事行业的人数逐渐增多,行业竞争也越来越大,招聘的企业和程序员们都想招聘到自己需要的人才/找到自己理想的岗位,国内大厂尤其是阿里招聘Java岗位居多,导致现在 Java 面试越来越难,内卷早就是大势所趋,万物皆可卷,卷的我们都见怪不怪了。 那么,阿里Java面试难度大吗?
|
3月前
|
NoSQL Java 关系型数据库
阿里技术三面:P7想靠资历打败我,却惨败于这800页面试热题下
阿里巴巴,这个中国互联网行业中能排上前三的企业,面试是非常讲究的。通常都是三面技术面+HR面,可是多少心怀阿里梦的工作者惨败三面之中,连HR面都没见着就败了。那如何通过技术三面呢?我来介绍介绍(这里是指我技术三面的经验)