首页
题库
公司真题
专项练习
面试题库
在线编程
面试
面试经验
AI 模拟面试
简历
求职
学习
基础学习课
实战项目课
求职辅导课
专栏&文章
竞赛
我要招人
发布职位
发布职位、邀约牛人
更多企业解决方案
AI面试、笔试、校招、雇品
HR免费试用AI面试
最新面试提效必备
登录
/
注册
klp
哈尔滨工业大学(深圳) 研发工程师
发布于广东
关注
已关注
取消关注
@程序员Hasity:
【腾讯】腾讯音乐后台一面,感觉还不错|0411
自我介绍http与https的区别TCP四次挥手,滑动窗口HTTP报文格式,基于TCP还是UDP网络IO模型Linux命令内存泄露和内存溢出线程池的参数线程池创建线程的方法线程池的运行机制线程池拒绝策略 什么时候拒绝springAOP的原理Spring事务的传播机制一个连表查询,员工表,部门表,查员工的部门经理场景题:设计一个秒杀系统手撕:求二叉树的最小高度手撕:找出N个递增数组的交集你的实习中最大的挑战是什么简单问了几个项目实现中的问题反问环节:部门技术栈本次面试的不足(腾讯音乐的面试官真的太nice了,给我详细讲解了我的情况)原贴:在学c语言的黑眼圈很自来熟面经专栏直通车,欢迎订阅:https://www.nowcoder.com/creation/manager/columnDetail/0xKkDM面经专栏下载, 点击跳转:https://github.com/Li-CW/Job-Hunter1. http与https的区别学习指引:只看这一篇就能搞懂Http和Https协议区别2. 讲一讲TCP四次挥手,滑动窗口参考回答:TCP四次挥手的过程:TCP四次挥手是用于终止一个TCP连接的过程,它由四个主要步骤组成。这个过程确保了双方都能够有序地关闭连接,并且释放相关资源。第一次挥手:客户端发送一个FIN报文段,用来关闭客户端到服务器的数据传送。这个报文段中包含了一个序列号,表示这是一个连接释放报文段。此时,客户端进入FIN_WAIT_1(终止等待1)状态,等待服务器的确认。第二次挥手:服务器收到FIN报文后,会发送一个ACK报文段作为应答。这个报文段中包含了确认号,用来确认已经收到了客户端的FIN报文段。此时,服务器进入CLOSE_WAIT(关闭等待)状态,TCP连接处于半关闭状态,即客户端已经没有数据要发送了,但服务器若发送数据,客户端仍要接受。客户端收到服务器的确认后,进入FIN_WAIT_2(终止等待2)状态,等待服务器发送连接释放报文段。第三次挥手:当服务器发送完所有数据后,会发送一个FIN报文段来关闭服务器到客户端的数据传送。这个报文段也包含了一个序列号,表示这是服务器发送的最后一个报文段。此时,服务器进入LAST_ACK(最后确认)状态,等待客户端的确认。第四次挥手:客户端收到服务器的FIN报文段后,发送一个ACK报文段进行确认。这个报文段中包含了确认号,用来确认已经收到了服务器的FIN报文段。此时,客户端进入TIME_WAIT(时间等待)状态,等待一段时间后进入CLOSED状态,连接正式关闭。而服务器在收到客户端的确认后,直接进入CLOSED状态。滑动窗口机制的工作原理:滑动窗口机制是TCP协议中实现流量控制和可靠传输的关键技术。它的主要工作原理如下:发送方维护一个发送窗口,这是一个连续的字节序列,表示发送方可以发送的字节数范围。发送窗口由两个参数定义:窗口的起始字节和窗口的大小。发送方将数据分成多个数据段,并按顺序发送到接收方。接收方使用确认号来通知发送方已成功接收到的数据。确认号表示接收方期望接收的下一个字节的序列号。同时,接收方还会通告一个窗口大小,告诉发送方自己的接收缓冲区还能容纳多少字节的数据。发送方根据接收方通告的窗口大小进行数据发送控制。如果接收方的窗口变大,发送方可以发送更多的数据;如果接收方的窗口变小,发送方需要适应减少的窗口大小。这样,发送方可以持续发送数据而不需要等待每个数据段的确认,从而提高了传输效率。滑动窗口机制在数据传输中起到了流量控制和可靠性传输的重要作用。通过动态调整窗口大小,接收方可以控制发送方的数据发送速率,避免网络拥塞和数据丢失。同时,滑动窗口机制还确保了数据的顺序传输和可靠接收,为TCP协议提供了可靠的传输服务。学习指引:计算机网络之TCP四次挥手3. HTTP报文格式,基于TCP还是UDP?参考回答:HTTP报文格式HTTP报文是HTTP应用程序之间发送的数据块,每条HTTP报文都包含一条来自客户端的请求,或者一条来自服务器的响应。它们由三个部分组成:对报文进行描述的起始行、包含属性的首部块,以及可选的、包含数据的主体部分。所有这些部分都是由CRLF(即“\r\n”)分隔的行组成的,最后一行之后还有一个CRLF表示报文的结束。HTTP请求报文HTTP请求报文由请求行(request line)、请求头部(header)、空行和请求数据4个部分组成,格式如下:<method> <URL> <Version> <Headers> <Request Body>* 请求行:包含一个方法和请求资源的URL以及HTTP的版本。例如:“GET /index.html HTTP/1.1”。 * 请求头部:包含关于请求的元数据,如Host、User-Agent、Accept、Content-Type、Content-Length、Cookie等。 * 空行:请求头部后会有一个空行,表示请求头部的结束。 * 请求数据:可选部分,用于POST或PUT方法中发送的数据。HTTP响应报文HTTP响应报文由状态行、响应头部、空行和响应正文4个部分组成,格式如下:<Version> <Status> <Reason-Phrase> <Headers> <Response Body>* 状态行:包含HTTP的版本,状态码和状态消息。例如:“HTTP/1.1 200 OK”。 * 响应头部:包含关于响应的元数据,如Content-Type、Set-Cookie、Cache-Control等。 * 空行:响应头部后会有一个空行,表示响应头部的结束。 * 响应正文:包含返回的数据,如HTML文件内容。HTTP是基于TCP还是UDP进行传输的?HTTP是基于TCP进行传输的。原因:可靠性:TCP是一个可靠的传输协议,它提供了数据包的排序和重传机制,确保数据能够完整、有序地到达目的地。HTTP需要这种可靠性来确保网页内容和其他数据的完整传输。流控制:TCP还提供了流量控制和拥塞控制机制,这有助于防止网络拥塞和数据丢失。对于像HTTP这样的大数据传输来说,这是非常重要的。连接管理:HTTP/1.1默认使用持久连接(也称为HTTP keep-alive),这意味着多个HTTP请求和响应可以通过同一个TCP连接连续发送。这提高了效率,因为不需要为每个请求/响应周期都建立和关闭连接。这种特性需要TCP的连接管理功能来支持。UDP是一个无连接的协议,不提供可靠性、排序或流控制。它更适合于实时应用,如VoIP、视频流或在线游戏,这些应用可以容忍偶尔的数据包丢失,但需要低延迟的传输。而HTTP则更注重数据的完整性和可靠性,因此选择TCP作为传输层协议更为合适。学习指引:一篇文章搞懂http协议(超详细)4. 网络IO模型参考回答:同步IO模型阻塞IO模型概念:在阻塞IO模型中,当应用程序调用一个IO函数(如read或write)时,如果数据未准备就绪,则该函数会阻塞当前线程,直到数据准备好为止。特点:简单直观,易于实现。但缺点是当进行IO操作时,线程会被挂起,无法执行其他任务,造成CPU资源的浪费。适用场景:适用于连接数较少,且对实时性要求不高的场景。应用例子:简单的文件读写操作,或者少量的网络连接处理。非阻塞IO模型概念:在非阻塞IO模型中,IO操作不会阻塞当前线程。如果数据未准备好,IO函数会立即返回,允许线程继续执行其他任务。特点:提高了线程的利用率,但缺点是需要频繁地检查IO状态,可能会增加CPU的负担。适用场景:适用于需要同时处理多个IO操作,且不希望线程被长时间阻塞的场景。应用例子:处理大量并发网络连接的服务器,如Web服务器。异步IO模型概念:在异步IO模型中,应用程序发起IO操作后,无需等待操作完成即可继续执行其他任务。当IO操作完成时,操作系统会通过回调函数或其他机制通知应用程序。特点:高度并发,能够充分利用CPU和IO资源。但需要复杂的编程模型和回调机制。适用场景:适用于需要处理大量并发IO操作,且对实时性要求较高的场景。应用例子:高性能的服务器应用程序,如实时数据分析系统。多路复用IO模型(select、poll、epoll等)select模型概念:select函数允许应用程序同时监听多个文件描述符的状态变化(如可读、可写等)。特点:能够处理多个IO事件,但受限于文件描述符的数量,且在高并发场景下性能可能下降。适用场景:适用于需要同时监控多个网络连接的状态变化的场景。应用例子:网络聊天服务器,需要同时处理多个客户端的连接和请求。poll模型概念:poll函数与select类似,也用于监听多个文件描述符的状态变化。不同之处在于poll没有文件描述符数量的限制。特点:能够处理大量文件描述符,但在高并发场景下性能可能不如epoll。适用场景:适用于需要监控大量网络连接的状态变化的场景。应用例子:大型网络游戏服务器,需要处理大量玩家的并发连接。epoll模型概念:epoll是Linux特有的IO多路复用机制,能够高效地处理大量并发连接。它通过事件驱动的方式来通知应用程序哪些文件描述符已经准备好进行IO操作。特点:性能高效,支持大量并发连接,且只在有事件发生时才通知应用程序,减少了不必要的CPU消耗。适用场景:适用于需要处理大量并发连接且对性能要求较高的场景。应用例子:高性能的Web服务器,如Nginx就使用了epoll模型来处理大量的HTTP请求。学习指引:[5种网络通信设计模型(也称IO模型)](https://www.cnblogs.com/god-of-death/p/7837695.html)5. Linux命令参考回答:文件操作:cp:复制文件或目录。例如,cp source_file destination 会将源文件复制到目标位置。mv:移动或重命名文件或目录。使用 mv old_name new_name 可以重命名文件。rm:删除文件或目录。例如,rm file_name 会删除指定的文件,而 rm -r directory_name 会递归删除目录及其内容。touch:创建空文件或更新文件的时间戳。例如,touch file_name 会创建一个新的空文件或更新现有文件的时间戳。目录管理:ls:列出当前目录中的文件和子目录。例如,ls -l 会以长格式显示目录内容。pwd:显示当前工作目录的路径。cd:切换工作目录。例如,cd /path/to/directory 会将当前工作目录更改为指定路径。mkdir:创建新目录。例如,mkdir directory_name 会创建一个新的目录。rmdir:删除空目录。例如,rmdir directory_name 会删除指定的空目录。权限设置:chmod:修改文件或目录的权限。例如,chmod 755 file_name 会设置文件的权限为拥有者读/写/执行、群组读/执行、其他人读/执行。chown:修改文件或目录的所有者。例如,chown owner:group file_name 会更改文件的所有者和群组。系统信息查看:cat /etc/os-release:查看操作系统版本信息。uname -a:查看Linux内核信息。df -h:查看各分区使用情况。du -sh <目录名>:查看指定目录的大小。free -m:查看内存使用量和交换区使用量(单位MB)。进程管理:ps:显示当前运行的进程信息。例如,ps aux 会显示所有用户的所有进程信息。kill:终止进程。例如,kill process_id 会终止指定ID的进程。top:实时显示进程状态。这个命令可以动态地显示系统中各个进程的资源占用状况,类似于Windows的任务管理器。学习指引:【Linux】Linux常用命令60条(含完整命令语句)6. 内存泄露和内存溢出参考回答:1. 内存泄露和内存溢出的定义内存泄露(Memory Leak): 指的是在程序运行过程中,动态分配的内存没有得到及时释放,导致系统内存的消耗随着程序运行时间的增加而增加,即使不再需要这些内存。简言之,内存泄露就是应该被释放的内存没有被释放。内存溢出(Memory Overflow): 当程序申请内存时,如果没有足够的可用内存空间来满足其需求,就会发生内存溢出。这通常发生在程序请求的内存超出了系统所能提供的范围,或者系统内存资源已被其他进程大量占用。2. 发生的原因内存泄露的原因:代码中存在循环引用,导致对象无法被垃圾收集器正确回收。注册了监听器或其他回调,但在不再需要时没有取消注册。静态集合类(如HashMap、HashSet)持有对象的引用,导致对象无法被回收。使用了长生命周期的对象来持有短生命周期对象的引用。使用了缓存或连接池等结构,但未能合理管理其生命周期。内存溢出的原因:程序中存在大量数据或对象,占用了过多内存。程序中存在内存泄露,随着时间的推移,占用的内存越来越多。系统分配给程序的内存不足,尤其是当程序运行在内存资源受限的环境中时。代码中可能存在大量的递归调用或循环创建对象,导致内存迅速被占满。3. 对计算机系统和程序的影响内存泄露的影响:随着程序运行时间的增长,内存占用会不断增加。如果不及时处理,可能导致系统内存耗尽,进而影响其他程序的运行或导致系统崩溃。长时间运行的程序可能会因为内存泄露而变得越来越慢,甚至出现卡顿、无响应等问题。内存溢出的影响:程序会因为无法申请到足够的内存而崩溃或出现异常。如果是在多线程环境下,内存溢出可能导致死锁或程序的不稳定。内存溢出可能导致数据丢失或损坏,尤其是在进行大量数据处理或存储时。4. 针对内存泄露和内存溢出的可能解决方案内存泄露的解决方案:使用专业的内存分析工具(如Eclipse MAT、VisualVM等)来检测和分析内存泄露的原因。编写代码时,注意合理管理对象的生命周期,避免不必要的长时间持有对象引用。使用弱引用(Weak Reference)或软引用(Soft Reference)来避免阻止垃圾收集器回收对象。在不再需要监听器或回调时,及时取消注册或断开连接。内存溢出的解决方案:优化程序算法和数据结构,减少内存占用。对于大量数据的处理,考虑使用分页、分块或流式处理的方式来减少内存占用。如果是Web应用,可以考虑使用缓存技术来减轻数据库压力,并减少内存中的数据量。在必要时,可以考虑增加系统内存或调整JVM的内存设置来适应程序的需求。监控程序的内存使用情况,及时发现并解决潜在的内存问题。学习指引:内存溢出和内存泄漏的区别7. 线程池的参数参考回答:核心线程数(corePoolSize):作用:这是线程池中正常情况下的线程数量,即使这些线程在空闲时也不会被销毁。如果线程池中的线程数量小于核心线程数,即使线程池中的其他线程处于空闲状态,也会创建一个新线程来处理新提交的任务。对性能的影响:较小的 corePoolSize 可能会导致任务等待时间增加,因为可能需要等待空闲线程来处理任务。而设置过大的 corePoolSize 可能会浪费系统资源,因为即使线程空闲也不会被销毁。最大线程数(maximumPoolSize):作用:这是线程池中允许的最大线程数量。当工作队列已满,且当前线程数小于 maximumPoolSize 时,线程池会再创建新的线程执行任务。对性能的影响:maximumPoolSize 限制了线程池在需要时能够扩展的线程数量。如果设置得太小,可能会导致任务不能及时得到处理。设置得过大,则可能导致过多的线程竞争CPU资源,从而降低系统性能。队列容量(BlockingQueue):作用:这是一个阻塞队列,用于存储待执行的任务。当线程池中的线程数量达到 corePoolSize 时,新提交的任务会被放入队列中等待处理。对性能的影响:队列的容量决定了在达到最大线程数之前,可以有多少任务在队列中等待。如果队列容量设置得太小,而任务提交速度又很快,那么可能会导致任务被拒绝。如果设置得太大,则可能会消耗过多的内存资源。线程存活时间(keepAliveTime):作用:当线程池中线程数量大于 corePoolSize 时,这是超出数量的空闲线程在终止前等待新任务的最长时间。对性能的影响:keepAliveTime 的设置可以帮助管理系统资源。较短的 keepAliveTime 会导致空闲线程更快地被销毁,从而释放系统资源。然而,如果设置得太短,可能会导致线程频繁地创建和销毁,这会增加系统开销。除了上述参数外,ThreadPoolExecutor 还有一个重要的参数是 RejectedExecutionHandler,它用于处理当线程池不能处理新任务时(例如,当线程池已关闭,或者已达到其最大容量并且工作队列已满)的情况。默认情况下,如果线程池不能处理新任务,会抛出一个 RejectedExecutionException。但是,你可以通过设置自定义的 RejectedExecutionHandler 来改变这一行为,例如可以选择在任务被拒绝时将任务放入一个溢出队列,或者简单地记录一个错误并丢弃任务。学习指引:Java线程池七个参数详解8. 线程池创建线程的方法参考回答:在Java中,线程池内部会维护一组工作线程,并根据需要创建、复用或销毁这些线程。线程池的初始化:当创建一个线程池实例时(如通过ThreadPoolExecutor类),你可以指定核心线程数、最大线程数、线程空闲时间、任务队列等参数。提交任务:当向线程池提交一个任务(Runnable或Callable)时,线程池会尝试找到一个可用的线程来执行任务。线程的创建与复用:如果当前线程数少于核心线程数,则创建一个新线程来执行任务。如果当前线程数已经达到核心线程数,但任务队列未满,任务会被添加到队列中等待执行。如果队列已满,且当前线程数未达到最大线程数,线程池会创建一个新线程(非核心线程)来执行任务。如果队列已满,且当前线程数已经达到最大线程数,则会根据设定的拒绝策略来处理新提交的任务。线程的复用:线程池中的线程在执行完一个任务后,并不会立即终止,而是会等待新的任务到来。这是通过循环从任务队列中取出任务来执行的机制实现的。如果线程池中的线程在一定时间内没有执行任务(这个时间可以通过keepAliveTime参数设置),并且当前线程数大于核心线程数时,这些额外的线程可能会被销毁,以减少资源占用。线程的销毁:当线程池被关闭或不再需要时,线程池中的线程会根据设置逐渐终止。如果线程池配置了允许核心线程超时, 那么在超时后核心线程也会被销毁。线程池的创建通常是通过ThreadPoolExecutor类来实现的,这个类提供了灵活的线程池配置选项。下面是一个创建ThreadPoolExecutor的示例:import java.util.concurrent.ArrayBlockingQueue;import java.util.concurrent.ThreadPoolExecutor;import java.util.concurrent.TimeUnit;public class ThreadPoolExample { public static void main(String[] args) { int corePoolSize = 2; // 核心线程数 int maximumPoolSize = 4; // 最大线程数 long keepAliveTime = 60L; // 线程空闲时间 TimeUnit unit = TimeUnit.SECONDS; // 时间单位 BlockingQueue<Runnable> workQueue = new ArrayBlockingQueue<>(10); // 任务队列 ThreadPoolExecutor executor = new ThreadPoolExecutor( corePoolSize, // 核心线程数 maximumPoolSize, // 最大线程数 keepAliveTime, // 线程空闲时间 unit, // 时间单位 workQueue, // 任务队列 new ThreadPoolExecutor.DiscardPolicy() // 拒绝策略 ); // 提交任务到线程池... // executor.execute(new MyRunnableTask()); // 关闭线程池(平滑关闭) // executor.shutdown(); }}在这个示例中,创建了一个ThreadPoolExecutor实例,配置了核心线程数、最大线程数、线程空闲时间、任务队列以及拒绝策略。然后,你可以通过executor.execute()方法提交任务到线程池中执行。学习指引:一文带你搞懂线程池原理以及6种创建方式9. 线程池的运行机制参考回答:线程池是一种用于管理和复用线程资源的技术,它能够在程序启动时创建多个线程,放入线程池中等待任务,当有任务需要执行时,就从线程池中获取一个空闲的线程来执行任务,任务执行完后线程并不立即销毁,而是等待下一个任务的到来。这样可以有效地复用线程资源,避免了频繁地创建和销毁线程所带来的开销。线程池的创建线程池的创建通常涉及以下几个步骤:初始化:确定线程池的基本参数,如核心线程数、最大线程数、队列深度等。配置线程工厂:用于创建新线程,可以设置线程的一些基本属性,如名称、优先级等。启动线程:根据配置的核心线程数,启动相应数量的线程,并放入线程池中等待任务。线程的管理与调度线程池内部维护着一组线程,以及一个任务队列。线程池的管理主要包括以下几个方面:线程数量控制:线程池会根据当前的任务量和线程状态动态调整线程数量,但通常不会超过预设的最大线程数。任务队列管理:当有新任务提交时,如果线程池中有空闲线程,则直接分配任务;如果没有空闲线程,任务会被放入任务队列中等待。线程状态监控:线程池会监控每个线程的状态,如是否空闲、是否在执行任务等。任务的分配与执行任务分配:当有任务提交到线程池时,线程池会尝试找到一个空闲的线程来执行任务。如果当前没有空闲线程,并且任务队列也未满,那么新任务就会被添加到任务队列中。任务执行:线程从任务队列中取出任务并执行。执行完毕后,线程会再次变为空闲状态,等待下一个任务的到来。线程的复用线程池的核心优势之一就是线程的复用。当一个线程完成任务后,它并不会立即销毁,而是重新变为空闲状态,等待下一个任务的分配。这样可以避免频繁地创建和销毁线程所带来的系统开销。线程池的销毁当线程池不再需要时,可以调用相应的销毁方法(如shutdown()或shutdownNow())来关闭线程池。在销毁过程中,线程池会停止接收新任务,等待所有已提交的任务执行完毕后,再关闭所有的线程资源。线程池在提高系统性能和响应速度方面的优势减少线程创建和销毁的开销:通过复用线程,避免了频繁地创建和销毁线程所带来的系统开销。提高系统资源利用率:线程池可以根据系统的实际情况动态调整线程数量,从而更有效地利用系统资源。提高响应速度:由于线程已经预先创建并处于等待状态,当有任务到来时,可以立即开始执行,无需等待线程的创建过程。任务管理更加灵活:通过线程池的任务队列,可以方便地管理和调度任务的执行顺序和优先级。提供了一定的容错能力:即使某个线程在执行任务时出错或崩溃,线程池也可以快速启动一个新的线程来替代它,从而保证了系统的稳定性和可用性。学习指引:Java线程池的创建和使用10. 线程池拒绝策略 什么时候拒绝参考回答:常见的拒绝策略类型及其作用AbortPolicy(默认):直接抛出RejectedExecutionException异常,阻止系统正常运行。这是一种比较严格的拒绝策略,通常用于重要任务,以确保系统不会因为过多的任务而崩溃。CallerRunsPolicy:该策略不会抛出异常或丢弃任务,而是将任务退回给调用者(即提交任务的线程)来执行。这通常用于非核心任务,可以避免任务被拒绝,但可能会增加调用者的负担。DiscardPolicy:不处理,直接丢弃任务,不予任何处理。这是一种比较宽松的拒绝策略,适用于那些不重要或可重复的任务。DiscardOldestPolicy:丢弃队列中最老的任务,然后重新尝试执行任务。这种策略在任务有时效性要求时比较有用,因为它可以确保新任务得到及时处理。拒绝策略的触发条件拒绝策略会在以下情况下被触发:线程池中的线程数量已达到最大线程数:这意味着无法再创建新的线程来处理新任务。任务队列已满:当任务队列(如BlockingQueue)已满,无法再添加新任务时。当这两个条件同时满足时,线程池就会根据配置的拒绝策略来处理新提交的任务。选择合适的拒绝策略取决于应用程序的具体需求和任务的重要性。例如,对于关键任务,可能会选择AbortPolicy以确保系统的稳定性;而对于非关键任务,可能会选择DiscardPolicy或CallerRunsPolicy来避免任务被拒绝。学习指引:浅谈java线程池什么时候触发拒绝策略11.springAOP的原理参考回答:AOP(面向切面编程)AOP(Aspect Oriented Programming,面向切面编程)是一种编程范式,旨在通过预定义的模式对程序的横切关注点进行模块化。这些横切关注点通常包括日志记录、事务管理、安全检查等跨越多个应用模块的功能。AOP通过将这些功能从业务逻辑中分离出来,提高了程序的可维护性和重用性。Spring AOP的实现方式Spring AOP是基于代理的AOP实现,它利用了Java的动态代理或CGLIB库来在运行时创建代理对象。Spring AOP默认使用Java动态代理来创建接口的代理实例,如果目标对象没有实现接口,则默认使用CGLIB来创建代理。关键组件的作用解释通知(Advice):通知是切面的一种实现,它描述了切面的行为以及何时执行该行为。Spring AOP支持五种类型的通知:前置通知(Before):在目标方法调用之前执行。后置通知(After):在目标方法调用之后执行,无论方法是否发生异常。返回通知(AfterReturning):在目标方法成功执行之后执行。异常通知(AfterThrowing):在目标方法抛出异常之后执行。环绕通知(Around):在目标方法调用前后都能执行,可以控制目标方法的执行。切点(Pointcut):切点定义了通知应该被应用到哪些方法上。它使用AspectJ的切点表达式语言来定义,可以灵活地匹配方法的签名。切面(Aspect):切面是通知和切点的结合。它定义了何时(when)、何地(where)以及如何(how)应用通知到目标方法上。切面负责将通知织入到目标对象的对应连接点上。整个流程的运行机制说明配置切面:在Spring配置文件中定义切面,包括切点和通知。这可以通过XML配置或使用注解来完成。创建代理:当Spring IoC容器启动时,它会根据配置创建切面,并为目标对象生成一个代理对象。这个代理对象会包含目标对象的所有方法,并且会在调用这些方法时执行相应的切面逻辑。方法调用:当客户端代码调用代理对象的方法时,Spring AOP会检查该方法是否与任何切点匹配。如果匹配,Spring AOP就会根据切面的配置,在方法调用之前、之后或周围执行相应的通知。执行通知:根据切面的配置,Spring AOP会在适当的时候执行通知。例如,如果配置了一个前置通知,那么该通知会在目标方法被调用之前执行。调用目标方法:在通知执行完毕后(如果是环绕通知,则在通知的逻辑中决定),Spring AOP会调用目标对象的实际方法。返回结果:目标方法执行完毕后,如果有后置通知或返回通知,Spring AOP会执行这些通知。最后,代理对象将目标方法的返回值返回给客户端。总的来说,Spring AOP通过动态代理和切面配置,实现了在不修改目标对象代码的情况下,动态地添加横切关注点功能,从而提高了代码的灵活性和可维护性。学习指引:Spring AOP(AOP概念、组成、Spring AOP实现及实现原理)12. Spring事务的传播机制参考回答:Spring框架的事务传播机制主要是定义了在多个事务方法相互调用时,事务是如何在这些方法间进行传播的。在Spring中,事务传播行为是通过Propagation枚举来定义的,它决定了当一个事务方法被另一个事务方法调用时,该如何使用事务。PROPAGATION_REQUIRED:如果当前没有事务,就新建一个事务,如果已经存在一个事务中,加入到这个事务中。这是最常见的选择。示例:方法A调用方法B,如果方法A已经在事务中,则方法B会加入到方法A的事务中;如果方法A不在事务中,那么方法B会开启一个新的事务。适用场景:当方法B需要参与到方法A的事务中时,或者方法B需要独立开启一个事务时。PROPAGATION_SUPPORTS:支持当前事务,如果当前没有事务,就以非事务方式执行。示例:如果方法A在事务中,方法B也会参与到这个事务中;但如果方法A不在事务中,那么方法B也会以非事务的方式执行。适用场景:方法B可以参与到其他方法的事务中,但如果被非事务方法调用,也能以非事务方式正常执行。PROPAGATION_MANDATORY:使用当前的事务,如果当前没有事务,就抛出异常。示例:如果方法A在事务中,方法B会加入到这个事务中;但如果方法A不在事务中,调用方法B会抛出异常。适用场景:方法B必须参与到其他方法的事务中,否则无法执行。除了上述三种传播行为,还有其他几种:PROPAGATION_REQUIRES_NEW:新建事务,如果当前存在事务,把当前事务挂起。这意味着无论方法A是否在事务中,方法B都会开启一个新的事务。PROPAGATION_NOT_SUPPORTED:以非事务方式执行,如果当前存在事务,就把当前事务挂起。即无论方法A是否在事务中,方法B都会以非事务的方式执行。PROPAGATION_NEVER:以非事务方式执行,如果当前存在事务,则抛出异常。即如果方法A在事务中,调用方法B会抛出异常。PROPAGATION_NESTED:如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,就执行REQUIRES_NEW行为。这是一个嵌套事务,它可以独立于父事务进行提交或回滚,但如果父事务回滚,它也会回滚。学习指引:带你读懂Spring 事务——事务的传播机制13. 一个连表查询,员工表,部门表,查员工的部门经理参考回答:假设员工表叫做 employees,部门表叫做 departments,并且这两张表的结构大致如下:employees 表列名数据类型描述employee_idINT员工的唯一标识符nameVARCHAR员工的姓名department_idINT员工所属的部门ID(外键)departments 表列名数据类型描述department_idINT部门的唯一标识符department_nameVARCHAR部门的名称manager_idINT部门经理的员工ID(对应employees表中的employee_id)基于这样的表结构,可以使用 SQL 的 JOIN 语句来关联这两张表,从而查询出每个员工的姓名、部门名称以及部门经理的姓名。以下是一个可能的 SQL 查询示例:SELECT E1.name AS employee_name, D.department_name, E2.name AS manager_name FROM employees E1 JOIN departments D ON E1.department_id = D.department_id LEFT JOIN employees E2 ON D.manager_id = E2.employee_id;这个查询做了以下几件事情:从 employees 表中选择员工的姓名(E1.name)。通过 department_id 关联 employees 表和 departments 表,以获取部门名称(D.department_name)。使用 LEFT JOIN 再次关联 employees 表(这次别名为 E2),以获取部门经理的姓名(E2.name)。这是通过匹配 departments 表中的 manager_id 和 employees 表中的 employee_id 来实现的。使用 LEFT JOIN 而不是 INNER JOIN 是为了确保即使某些部门没有指定经理(即 manager_id 为空),查询结果仍然能包含该部门下的员工信息,只是部门经理姓名会显示为 NULL。14. 场景题:设计一个秒杀系统参考回答:一、核心功能设计商品服务:负责管理商品信息,包括商品的库存、价格等。在秒杀活动开始前,应提前将商品信息加载到Redis等缓存中,以减少对数据库的访问压力。订单服务:负责生成和管理订单。在秒杀过程中,订单服务需要快速响应并处理大量的并发请求。用户服务:管理用户信息和用户状态,包括用户的秒杀资格、购买记录等。秒杀服务:负责处理秒杀逻辑,包括验证用户资格、扣减库存、生成订单等。二、高并发处理策略限流:使用令牌桶、漏桶等算法限制单位时间内的请求数量,防止系统过载。异步处理:将部分非实时性要求较高的业务逻辑进行异步处理,如发送通知、更新统计信息等。分布式锁:利用Redis等实现分布式锁,确保同一时刻只有一个请求能够修改库存,防止超卖。负载均衡:通过Nginx等反向代理服务器实现请求的负载均衡,分散到多个秒杀服务实例上。三、数据库事务一致性使用关系型数据库的事务功能:确保在秒杀过程中,商品的扣减和订单的生成等操作在同一个事务中完成,保持数据的一致性。分布式事务:如果秒杀系统涉及多个微服务间的数据一致性,可以考虑使用分布式事务解决方案,如Seata等。四、前端体验优化异步加载:使用Ajax等技术异步加载数据,提高页面响应速度。倒计时:在秒杀活动开始前显示倒计时,提醒用户做好准备。排队机制:如果秒杀请求过多,可以实现一个排队机制,让用户知道自己在队列中的位置,减少用户的焦虑感。友好的错误提示:当用户秒杀失败时,给出明确的错误提示,如“库存不足”等。五、错误处理和监控全局异常处理:在后端实现全局的异常处理机制,记录错误信息并返回给用户友好的提示。日志收集与分析:使用ELK(Elasticsearch、Logstash、Kibana)等技术栈进行日志的收集与分析,便于问题追踪和定位。性能监控与告警:利用Prometheus、Grafana等工具进行实时监控,并设置合理的告警阈值,确保系统稳定运行。熔断与降级:在微服务架构中,实施熔断和降级策略,当某个服务出现故障时,能够快速隔离并降级处理,保证整体系统的可用性。
点赞 23
评论 2
全部评论
推荐
最新
楼层
暂无评论,快来抢首评~
相关推荐
07-30 11:52
门头沟学院 Java
美团正式批开了
美团暑期实习没投递成功,这次正式批的北斗计划总该有我的一部分了吧!
求职的纳鲁多:
大佬投我就不投了,毕竟王不见王,避你锋芒
点赞
评论
收藏
分享
07-30 11:56
江西理工大学 Java
小鹏ai面后挂
我发誓永远不买小鹏汽车
小鹏汽车AI面37人在聊
点赞
评论
收藏
分享
07-03 16:13
嘉应学院 Python
请问这个是骗子吗😂
xiaolihuam...:
很明显骗子,如果是hr直接约你面试了,哪用得着内推,如果是员工的话,你得多优秀,一线员工直接加你微信,
点赞
评论
收藏
分享
07-08 20:34
宁夏理工学院 软件测试
25应届生
是我简历有问题吗?求评
程序员小白条:
学历GG,这个排版布局,还有行间距和字缩进不大行,女生自我要求应该更高才是,没内容,起码美观这块要做好
投了多少份简历才上岸
点赞
评论
收藏
分享
08-01 15:40
已编辑
门头沟学院 客户端其它
想把公司炸了!!!
我女朋友来找我了,但是我项目节点要交付,TMD,最近天天加班,身心俱疲,所以,我在此收集花花和点赞。花花破50,点赞破100,我给大家表演一个炸公司
码农索隆:
很好,我周六也来加班了,草
牛友故事会
点赞
评论
收藏
分享
评论
点赞成功,聊一聊 >
点赞
收藏
分享
评论
提到的真题
返回内容
全站热榜
更多
1
...
百度提前批,三面被推迟一周,喜提秋招第一凉
7614
2
...
虾皮秋招一面
3255
3
...
百度提前批 三面
2800
4
...
他拿大厂SSP Offer打牌是什么概念啊?25届双非之光
2728
5
...
小鹏offer
1559
6
...
被猿辅导挂了简历,但我想说...
1442
7
...
虾皮一面凉经
1375
8
...
最强本科✌
1347
9
...
上班一周,工资还没拿,先欠公司两千
1296
10
...
大学四年,我感觉我像个“孤勇者”
1236
创作者周榜
更多
正在热议
更多
#
简历上的经历如何包装
#
29575次浏览
821人参与
#
秋招被确诊为……
#
164160次浏览
752人参与
#
中兴秋招
#
205751次浏览
2296人参与
#
工作中哪个瞬间让你想离职
#
63707次浏览
569人参与
#
你最希望上岸的公司是?
#
135225次浏览
706人参与
#
和同事相处最忌讳的是__
#
24469次浏览
244人参与
#
25届网易互娱暑实进度
#
78430次浏览
702人参与
#
虾皮求职进展汇总
#
249466次浏览
1856人参与
#
投格力的你,拿到offer了吗?
#
86797次浏览
583人参与
#
2022毕业即失业取暖地
#
102716次浏览
662人参与
#
2022毕业生求职现身说法
#
89298次浏览
700人参与
#
秋招OC许愿
#
327820次浏览
2450人参与
#
你最近一次加班是什么时候?
#
71005次浏览
350人参与
#
26届的你,投了哪些公司?
#
45326次浏览
497人参与
#
你的秋招第一面感觉怎么样
#
76936次浏览
592人参与
#
柠檬微趣工作体验
#
6743次浏览
40人参与
#
你遇到最难的面试题目是_
#
16694次浏览
201人参与
#
我对___祛魅了
#
48589次浏览
441人参与
#
地平线求职进展汇总
#
52656次浏览
370人参与
#
研究所VS国企,该如何选
#
194851次浏览
1819人参与
#
如果校招重来我最想改变的是
#
271928次浏览
2853人参与
牛客网
牛客网在线编程
牛客网题解
牛客企业服务