Java Spring “IOC + DI”面试清单(含超通俗生活案例与深度理解)

++记得评论区领专属红包🧧++

一、请解释什么是 IOC(控制反转)?什么是 DI(依赖注入)?两者的关系是什么?

• 核心回答:IOC 是一种颠覆传统对象管理逻辑的设计思想------过去开发时,若类 A 需要依赖类 B 完成功能,开发者必须在 A 的代码里手动写 new B() 创建实例,还要处理 B 依赖的其他类(比如 B 依赖 C,就得先在 A 里 new C、再用 C 实例化 B),相当于"自己包揽所有'找帮手'的工作";而 IOC 模式下,开发者只需告诉 Spring 容器"我需要 A 类来做什么",容器会主动完成 A 的创建、A 依赖的 B 的创建,以及 B 依赖的 C 的创建,最后把能直接用的 A 实例交给开发者。DI 是 IOC 思想的具体落地手段,指容器在创建对象时,会自动把该对象需要的依赖(比如 A 要的 B)"主动送过去",不用开发者手动关联依赖关系。简单说,IOC 是"让别人帮你统筹安排"的想法,DI 是"别人具体帮你送东西"的动作,两者是"思想与实现"的关系。

• 生活案例:用"组织家庭聚餐"来类比最贴近日常。以前自己办聚餐(传统开发模式),要亲自做三件事:一是列清单(确定依赖),比如"要做番茄炒蛋、可乐鸡翅、凉拌黄瓜,需要番茄、鸡蛋、鸡翅、可乐、黄瓜";二是采购(new 对象),得自己去超市买番茄、挑鸡蛋、选鸡翅,少一样都做不了菜;三是备菜(关联依赖),比如做可乐鸡翅前,要先把鸡翅洗干净、焯水,再准备可乐,一步都不能少,要是忘了买可乐(漏写 new 依赖),鸡翅就没法做。现在找"上门厨师服务"(Spring 容器)帮忙(IOC 思想),你只需要告诉厨师"周末中午 10 人聚餐,要 3 个热菜、2 个凉菜"(声明需求),厨师会自己做三件事:一是列食材清单(解析依赖),比如"番茄炒蛋要中等番茄 3 个、土鸡蛋 6 个,可乐鸡翅要鸡翅中 2 斤、可乐 1 瓶";二是采购食材(创建对象),厨师会联系菜场配送,不用你跑超市;三是备菜做菜(注入依赖),厨师会把焯好水的鸡翅和可乐一起倒进锅里(给鸡翅注入可乐依赖),做好的菜直接端上桌------你不用管食材怎么来、依赖怎么配,只负责招呼客人(专注业务逻辑),这就是 IOC;而厨师把可乐倒进鸡翅锅、把鸡蛋打进番茄碗的动作,就是 DI。

• 思考:IOC 的核心价值不是"少写几行 new 代码",而是"彻底解耦"------就像聚餐时你和菜场解耦,不用关心菜场在哪、食材多少钱;开发中,对象和对象的创建逻辑解耦,比如后来想把可乐鸡翅换成红烧鸡翅(改 B 类为 B1 类),不用去改所有用到 B 类的代码(比如 A 类),只需告诉容器"现在要 B1 类",容器会自动用 B1 替代 B 注入给 A。另外,DI 有三种常见方式:构造器注入(厨师必须先拿到鸡翅才能开始做,依赖不可缺)、setter 注入(厨师可以先做其他菜,等可乐到了再做鸡翅,依赖可选)、字段注入(厨师直接用备好的食材,不用自己拿),日常开发中构造器注入更推荐,因为能确保依赖不缺失,避免后续用的时候才发现"少了食材"。

二、你理解的 Spring IOC 核心实现机制是什么?可以结合生活场景说说吗?

• 核心回答:Spring IOC 本质是一个"智能化对象生产工厂",能按需求自动创建、管理对象,核心靠四个关键环节协同:① 配置解析:把 XML 配置、注解(如 @Component)翻译成容器能懂的"生产说明书"(BeanDefinition),明确要做什么对象、需要什么属性、依赖哪些其他对象;② 反射机制:不用手动 new,通过类的全路径(如"com.xxx.UserService")拿到类的字节码信息,动态创建对象,相当于工厂的"万能生产工具";③ 工厂模式:容器统一管理对象创建逻辑,比如单例对象要查库存、多例对象要新生产,避免每个对象都写一套创建流程;④ 单例缓存:创建好的单例对象存到类似 HashMap 的"成品仓库",下次用直接拿,不用重复生产,节省资源。这四个环节缺一个都不行------没有配置解析,容器不知道要做什么;没有反射,没法灵活创建不同对象;没有工厂模式,创建逻辑会混乱;没有缓存,会浪费内存和时间。

• 生活案例:用"社区面包店的日常运营"来类比,面包店(Spring 容器)要给居民做各种面包(对象),核心流程就是 IOC 的实现机制:① 配置解析:居民通过微信小程序下单(配置),比如"李阿姨:2 个全麦面包(无糖)、1 个牛角包(黄油味);张先生:1 个吐司(切片)、3 个肉松小贝",店员把这些订单整理成"生产清单"(BeanDefinition),清单上写清楚"全麦面包:面粉 200g、酵母 2g、无蔗糖,烤 15 分钟;牛角包:面粉 150g、黄油 50g,烤 12 分钟"------这一步就是把"用户需求"(配置)翻译成"可执行的生产标准",店员还会检查"全麦面粉够不够"(类路径是否存在),不够就及时跟李阿姨说(启动报错),不会等烤的时候才发现没面粉。② 反射机制:面包师的"多功能烤箱"就是反射工具,烤箱不用居民自己操作(手动 new),而是根据生产清单上的"面包类型+配方"(类路径+属性),自动调整温度和时间(创建对象),比如烤全麦面包就调 180℃、15 分钟,烤牛角包就调 190℃、12 分钟;就算配方改了(类的构造方法变了),比如全麦面包要加核桃,只要清单上写清楚(类路径对),烤箱只需加个"撒核桃"的步骤(反射逻辑微调),不用换烤箱(改核心工具)。③ 工厂模式:面包店有固定的"生产流程"(工厂逻辑),比如每天早上 6 点备料、7 点开始烤、8 点包装、9 点配送,不管是做全麦面包、牛角包还是吐司(不同对象),都按这个流程来;比如有居民临时加订"1 个脏脏包"(新增对象),不用改流程,只需把脏脏包的配方加进生产清单,面包师按流程烤就行------这就是统一工厂逻辑的好处,避免混乱,比如不会因为加了脏脏包就改成下午备料。④ 单例缓存:面包店有个"热销品货架"(单例缓存),比如全麦面包每天卖得最多,面包师会多烤一些放货架上,下次李阿姨再买,店员直接从货架拿(从缓存取),不用让面包师再烤(重复创建);只有冷门的面包,比如"提拉米苏面包"(多例对象),每次有人订,面包师才现烤,不存货架------这对应 Spring 里的单例和多例,常用对象存缓存,节省时间和原料(内存)。

• 思考:很多人担心"反射比手动 new 慢",其实 Spring 用单例缓存完美解决了这个问题------单例对象只反射创建一次,后续用缓存,性能影响几乎可以忽略;而多例对象本身就是要每次新创建,反射的开销在日常开发中完全可接受。另外,工厂模式让 IOC 有很强的扩展性,比如后来面包店要加"定制蛋糕"业务(新增对象类型),只需在生产流程里加"蛋糕裱花"的步骤(扩展工厂逻辑),不用重构整个面包店;开发中也是如此,Spring 支持自定义 BeanFactory,开发者可以按业务需求加逻辑,比如对所有对象加日志打印,只需改工厂逻辑,不用改每个对象的代码。

三、BeanFactory 和 ApplicationContext 有什么区别?分别适合什么场景?

• 核心回答:BeanFactory 是 Spring IOC 的"基础款工具",相当于"手动档自行车",功能极简且"按需工作";ApplicationContext 是"豪华款电动车",继承了 BeanFactory 所有功能,还加了很多实用特性,且"主动就绪"。具体区别有三点:① 加载方式:BeanFactory 是"懒加载",只有调用 getBean() 时才创建对象,像自行车"你不蹬就不走";ApplicationContext 是"预加载",容器启动时就创建所有单例对象,像电动车"通电就 ready,拧油门就走"。② 功能丰富度:BeanFactory 只有"获取对象"的核心功能,不能自动处理国际化、事件发布,像自行车只有"代步"功能,没有灯、没有储物筐;ApplicationContext 新增了国际化(多语言支持)、事件发布(模块间通信)、自动注册后置处理器(全局对象增强)等,像电动车有大灯、USB 充电、储物筐,功能齐全。③ 面向人群:BeanFactory 是 Spring 框架的"底层骨架",面向框架内部开发;ApplicationContext 是"开发者工具",面向日常业务开发。

• 生活案例:用"旅行装备"对比更易理解------BeanFactory 像"手动折叠伞",ApplicationContext 像"全自动晴雨伞"。先看 BeanFactory(手动折叠伞):它的核心作用只有"遮雨"(获取 Bean),而且需要你"手动撑开、手动收起"(调用 getBean()),不用的时候就放包里(不创建 Bean);它没有额外功能,比如不能自动防晒(不能自动注册 BeanPostProcessor)、不能一键开合(不能发布事件),如果遇到大风(复杂依赖),得自己调整握伞姿势(手动配置依赖),不小心还会被风吹翻(遗漏配置)。再看 ApplicationContext(全自动晴雨伞):它能"遮雨"(继承 BeanFactory 功能),还能"自动防晒"(预加载单例 Bean)、"一键开合"(容器启动就准备好对象)、"抗大风"(自动处理依赖冲突)、"夜间反光条"(支持国际化、事件发布);比如你去旅行(项目启动),提前把全自动伞打开(容器启动),遇到下雨直接用(调用 Bean),不用临时找按钮撑开(手动 getBean());如果伞骨断了(依赖缺失),伞会有轻微卡顿提醒(启动时报错),不会等到下雨时才发现用不了(调用 getBean() 才报错);如果你想让同行的人也用伞(多模块通信),只需喊一声(发布事件),不用手动递伞(手动调用其他 Bean)。

再看适用场景:BeanFactory 适合"资源极度有限"的场景,比如"户外徒步旅行"------徒步时背包重量要控制在 10 斤以内(内存有限),手动折叠伞重 100g(占用资源少),功能只要"遮雨"(简单 Bean 获取),完全够用;全自动晴雨伞重 300g(占用资源多),还带反光条、防晒涂层(用不上的功能),反而增加背包负担。再比如"嵌入式设备开发",比如智能手表的系统(内存只有 2MB),需要一个"时间同步"的工具 Bean,用 BeanFactory 就能满足需求,不用启动复杂的 ApplicationContext。ApplicationContext 适合"功能复杂、追求效率"的场景,比如"城市通勤"------通勤时要赶地铁、避太阳、临时装文件(多业务需求),全自动晴雨伞的防晒、储物功能(国际化、事件发布)能省很多事;再比如"电商网站后台",需要用户注册、订单支付、物流跟踪多个模块,模块间要通信(支付成功后通知物流),还要支持中文、英文(国际化),用 ApplicationContext 能自动处理这些需求,不用手动写大量配置。

• 思考:实际开发中很少直接用 BeanFactory,除非是嵌入式开发或极简工具项目。有人会问"ApplicationContext 预加载会不会浪费内存?",其实单例 Bean 本身就是要长期使用的,预加载只是"提前占用内存",避免后续使用时的延迟;而且预加载能提前暴露错误,比如某个 Bean 的依赖不存在,ApplicationContext 启动时就报错,BeanFactory 要到调用 getBean() 时才报错------线上系统中,启动时报错能及时修复,调用时报错会影响用户,所以 ApplicationContext 更适合生产环境。另外,ApplicationContext 有很多实现类,比如 ClassPathXmlApplicationContext(加载 XML 配置)、AnnotationConfigApplicationContext(加载注解配置),就像全自动晴雨伞有"折叠款""直柄款",核心功能一样,只是适配不同使用习惯(配置方式),开发者可以按项目需求选。

四、Spring 容器启动阶段主要做了哪些工作?请用生活例子辅助说明。

• 核心回答:Spring 容器启动阶段的核心是"做准备,不干活"------就像"烘焙蛋糕前的备料阶段,只洗水果、打蛋液,不开烤箱烤蛋糕",这个阶段不会创建 Bean,只会为后续创建 Bean 打基础,主要分三步:① 加载配置元数据:容器找到开发者写的配置(XML、@ComponentScan、@Bean),这些配置像"蛋糕食谱",告诉容器要做哪些"蛋糕"(Bean)、需要什么"原料"(依赖);② 解析配置元数据:容器把"食谱"翻译成"标准化备料清单"(BeanDefinition),比如把"@Component("cakeService") public class CakeService { @Autowired private MilkDao milkDao; }"解析成"Bean 名:cakeService,类型:com.xxx.CakeService,依赖:milkDao,作用域:单例",同时检查配置是否正确(比如类路径是否存在);③ 注册 BeanDefinition:把解析好的"备料清单"存到"清单仓库"(BeanDefinitionRegistry),像厨房的"原料架标签",每个清单对应一个标签,方便后续"烤蛋糕"(创建 Bean)时快速查找。

• 生活案例:用"婚礼筹备的'前期准备阶段'"来类比,婚礼筹备组(Spring 容器)的前期准备(启动阶段)不会开始举办婚礼(创建 Bean),而是做三件事:① 加载配置元数据:筹备组收集新人的需求(配置),比如"婚礼主题:森系,宾客人数:100 人,餐标:每桌 12 个菜(5 热 5 凉 2 甜品),流程:接亲→仪式→晚宴"------这些需求可能来自新人的口头描述(@Bean 注解)、婚庆公司的合同(XML 配置)、亲友的建议(@ComponentScan),筹备组会统一收集起来,确保没有遗漏。② 解析配置元数据:筹备组把"新人需求"翻译成"具体执行清单"(BeanDefinition),比如:"接亲环节:需要 2 辆婚车(白色宝马)、6 个伴郎伴娘(统一穿浅绿礼服)、10 个接亲游戏道具(藏婚鞋、猜谜语);晚宴环节:每桌 1 个主菜(清蒸石斑鱼)、2 个甜品(慕斯蛋糕、蛋挞),饮料要可乐、果汁、红酒各 1 瓶"------这个过程中,筹备组会检查"资源是否够"(配置是否正确),比如发现婚车只有 1 辆(类路径错误,比如 MilkDao 类不存在),会立刻联系租车公司加订(容器启动时报错),不会等到接亲当天才发现车不够(创建 Bean 时报错);还会确认"流程是否合理",比如接亲时间不能和仪式时间冲突(依赖是否正确,比如 cakeService 依赖的 milkDao 是否有定义),避免婚礼当天混乱。③ 注册 BeanDefinition:筹备组把"执行清单"分配给各个负责人(BeanDefinitionRegistry),比如"婚车负责人:张哥,负责 2 辆宝马的调度;餐饮负责人:李姐,负责每桌 12 个菜的准备;游戏负责人:王哥,负责 10 个接亲道具的采购"------每个负责人手里的清单就是"BeanDefinition",上面写着"要做什么、需要什么资源、什么时候完成";这样婚礼当天(创建 Bean 阶段),张哥直接按清单调度婚车(查找 BeanDefinition 创建婚车相关 Bean),不用再问筹备组"要什么车、接亲路线是什么"(容器不用再解析配置),节省时间;如果新人临时加"签到墙环节"(新增 Bean),只需写一张签到墙的执行清单,交给新的负责人(注册新的 BeanDefinition),不用改其他负责人的清单(不影响已有配置)。

• 思考:容器启动阶段的"错误检查"非常关键,比如配置里写了一个不存在的类,或者一个 Bean 依赖的另一个 Bean 没定义,容器在解析配置时就会报错,不会等到创建 Bean 时才发现------这就像婚礼筹备时发现婚车不够,及时加订,不会等到接亲时才让新人着急;线上项目中,启动阶段报错能让开发人员及时修复,避免用户使用时出现问题。另外,配置元数据的来源可以多样,比如有的项目用 XML 配置 Bean,有的用注解,有的用 JavaConfig,但容器会统一解析成 BeanDefinition,就像婚礼需求不管是新人说的、合同写的,还是亲友建议的,筹备组都会统一整理成执行清单,确保后续执行流程一致;这种"统一格式"让 Spring 能支持多种配置方式,开发者不用受限于一种,更灵活。

五、请详细说说 Spring Bean 的完整生命周期?结合生活场景解释每个阶段。

• 核心回答:Spring Bean 的生命周期是从"容器创建"到"容器销毁"的全过程,像"一家奶茶店从开业到闭店转让"的完整流程,分四大阶段:实例化(店铺装修)、属性赋值(采购设备原料)、初始化(员工培训试营业)、销毁(清货闭店),每个阶段还穿插容器的"辅助操作"(Aware 接口、BeanPostProcessor),确保 Bean 能正常工作。具体步骤按顺序:1. 实例化:容器用反射调用 Bean 的无参构造,创建"空壳"对象,属性都是默认值(如 String 为 null);2. 属性赋值:容器按配置给 Bean 设属性,包括注入依赖的其他 Bean;3. BeanNameAware 回调:容器告诉 Bean"你的唯一标识是什么"(调用 setBeanName);4. BeanFactoryAware 回调:容器告诉 Bean"你属于哪个容器"(调用 setBeanFactory);5. BeanPostProcessor 前置处理:全局后置处理器对 Bean 做初始化前检查(如属性合法性);6. InitializingBean 回调:Bean 执行核心初始化(如加载业务配置);7. 自定义 init 方法:执行开发者自定义的初始化(如调试设备);8. BeanPostProcessor 后置处理:全局后置处理器对 Bean 做完善(如添加功能标识);9. Bean 可用:Bean 存入缓存,开发者可调用其方法处理业务;10. DisposableBean 回调:容器销毁时,Bean 执行核心销毁(如关闭核心资源);11. 自定义 destroy 方法:执行开发者自定义的销毁(如清理剩余资源)。

• 生活案例:用"新开一家'元气奶茶店'"的完整流程类比(奶茶店=Bean,加盟总部=Spring 容器),每个阶段对应得非常清晰:

  1. 实例化(店铺装修,搭起空壳):加盟总部帮你找好店铺位置,开始装修(容器调用构造方法),刷上奶茶店的招牌色、装上门头(创建"空壳"对象)------此时店铺只有"壳子",没有设备、没有原料(Bean 的属性都是默认值,比如 MilkService 的 milkDao 是 null);就像刚实例化的 Bean,只有对象结构,没有具体属性和依赖。

  2. 属性赋值(采购设备原料,配齐基础资源):总部给你配送奶茶设备(属性赋值),比如收银机、制冰机、封口机,还送第一批原料(依赖的 Bean),比如牛奶、茶叶、珍珠(注入 MilkDao、TeaDao)------你把设备摆进店铺,原料放进冷藏柜(属性设置完成),此时店铺有了"基础运营资源",就像 Bean 有了属性和依赖,不再是"空壳"。

  3. BeanNameAware 回调(拿到店铺编号,确定身份):总部给你发"店铺授权书",上面写着"你的店铺编号是 YQ2024001,这是你在总部系统的唯一标识,进货、对账都要用它"(容器调用 setBeanName),你把编号贴在收银台(Bean 知道自己的 Bean 名称)------就像 Bean 知道自己在容器中的名字,后续总部查找它时,就用这个标识。

  4. BeanFactoryAware 回调(了解所属总部,明确管理方):总部给你发"运营手册",手册上写着"你属于元气奶茶华东总部,有问题联系区域经理,电话 138XXXX1234"(容器调用 setBeanFactory),你把手册放在前台(Bean 知道自己所属的 BeanFactory)------比如你想申请新品原料(Bean 想获取其他资源),就知道要联系华东总部(容器),不用找错部门。

  5. BeanPostProcessor 前置处理(总部检查,确保合规):总部派督导上门检查(全局后置处理器的前置处理),看设备是否安装正确(检查 Bean 属性是否合法)、原料是否在保质期内(检查依赖是否有效),还提醒你"收银机要每天对账、制冰机要定期清理"(给 Bean 加基础规则)------这是初始化前的"合规检查",确保店铺符合运营标准,就像 Bean 初始化前被检查,避免后续出问题。

  6. InitializingBean 回调(培训核心技能,完成基础准备):督导给你和员工做"核心运营培训"(容器调用 afterPropertiesSet),比如怎么煮珍珠、怎么调奶茶甜度、怎么用收银机下单(Bean 的核心初始化逻辑)------这是成为"合格奶茶店"的必要步骤,不学这些就没法做奶茶(Bean 不做核心初始化,就没法正常工作);比如 MilkService 实现 InitializingBean,在 afterPropertiesSet 里初始化牛奶进货渠道,这是 MilkService 能提供牛奶的核心前提。

  7. 自定义 init 方法(调试设备试做,优化细节):你和员工自己试做奶茶(自定义 init 方法,比如 @PostConstruct 注解的方法),调整茶叶浸泡时间、测试收银机支付功能(开发者自定义的初始化逻辑)------这不是必须的,但能让店铺运营更顺畅(Bean 更满足业务需求);比如你加一个 @PostConstruct 方法,把常用的"三分糖奶茶"配方存进收银机快捷键,提高点单效率,这是自定义的优化操作。

  8. BeanPostProcessor 后置处理(拿到营业资质,正式就绪):总部给你发"营业执照"和"卫生许可证"(后置处理器的后置处理),还帮你开通"线上外卖平台"(给 Bean 加额外功能)------此时你的店铺是"完全合格的运营主体"(Bean 初始化完成),可以开门迎客(Bean 可以被使用);比如 Spring AOP 就是通过 BeanPostProcessor 后置处理,给 Bean 生成代理对象,实现订单日志、支付事务等功能,就像外卖平台让奶茶店多了"线上接单"的能力。

  9. Bean 可用(正常营业,处理业务):你每天开门营业,做奶茶、接待客人、处理外卖订单(开发者调用 Bean 的方法处理业务)------比如客人点一杯"珍珠奶茶三分糖"(调用 milkService.getMilk() 配合 teaService.makeTea() 处理业务),这是 Bean 的核心作用阶段,就像奶茶店的主要任务是卖奶茶,Bean 的主要任务是处理业务逻辑。

  10. DisposableBean 回调(申请闭店,清理核心资源):因为个人原因你决定闭店(容器销毁),向总部申请"闭店手续"(容器调用 destroy),交还"店铺授权书"、注销外卖平台账号(关闭 Bean 的核心资源,比如 MilkService 关闭牛奶进货渠道连接),确认"没有未对账的订单、没有过期原料"(检查 Bean 是否有未回收的资源)------这是销毁前的"必要步骤",不办闭店手续就没法注销店铺(Bean 不关闭核心资源,会导致内存泄漏)。

  11. 自定义 destroy 方法(清货转让,处理剩余资源):你把剩余的原料低价卖给其他奶茶店(自定义 destroy 方法,比如 @PreDestroy 注解的方法),把设备打包转让、清理店铺卫生(处理 Bean 的自定义资源,比如 MilkService 清空本地原料库存记录)------这是开发者自定义的"收尾操作",让 Bean 销毁得更彻底;比如一个文件处理 Bean,在 @PreDestroy 方法里删除临时生成的订单报表,避免占用磁盘空间。

最后,总部从系统中删除你的店铺编号(容器销毁 Bean),奶茶店正式闭店(Bean 生命周期结束)------整个过程和 Bean 的生命周期完全对应,每个步骤都有"总部辅助"和"店铺自身操作",确保 Bean 从创建到销毁都能"合规、高效"。

• 思考:开发中要注意三个关键点:① 初始化顺序:InitializingBean 的 afterPropertiesSet 先执行,再执行自定义 init 方法(如 @PostConstruct),因为 afterPropertiesSet 是 Spring 内置接口,优先级更高;比如奶茶店先参加总部的核心培训(afterPropertiesSet),再自己试做奶茶(自定义 init),逻辑上更合理。② BeanPostProcessor 是"全局生效"的,比如一个 BeanPostProcessor 会对所有 Bean 做前置和后置处理,所以要注意过滤不需要处理的 Bean(比如通过 Bean 名称或类型判断),避免浪费资源;比如总部督导只检查奶茶店,不检查总部自己的行政部门,就是一种过滤。③ 多例 Bean 的销毁:只有单例 Bean 会被容器销毁(执行 DisposableBean 和自定义 destroy 方法),多例 Bean 创建后由开发者自己管理,容器不会管,就像总部只负责直营店(单例)的闭店手续,加盟店(多例)自己负责闭店,总部不干预;另外,@PostConstruct 和 @PreDestroy 注解比实现接口更解耦,因为不用让 Bean 依赖 Spring 的类,后续换成其他框架也方便,推荐日常开发使用。

相关推荐
crystal_pin3 小时前
axios统一封装的思路
面试
ThisIsMirror3 小时前
CompletableFuture并行任务超时处理模板
java·windows·python
笔尖的记忆3 小时前
【前端架构和框架】react组件化&数据流
前端·面试
小小前端_我自坚强4 小时前
UniApp 微信小程序开发使用心得
面试·微信小程序·代码规范
im_AMBER4 小时前
Web 开发 24
前端·笔记·git·学习
珹洺4 小时前
Java-Spring入门指南(二十一)Thymeleaf 视图解析器
java·开发语言·spring
源码集结号4 小时前
一套智慧工地云平台源码,支持监管端、项目管理端,Java+Spring Cloud +UniApp +MySql技术开发
java·mysql·spring cloud·uni-app·源码·智慧工地·成品系统
EnCi Zheng4 小时前
Spring Security 最简配置完全指南-从入门到精通前后端分离安全配置
java·安全·spring
程序员小假4 小时前
为什么这些 SQL 语句逻辑相同,性能却差异巨大?
java·后端