深入Lombok原理:注解处理器与字节码操作实战
简介这份资源围绕 Lombok 的实现原理展开面向希望深入理解注解处理器与编译期字节码增强机制的 Java 开发者尤其适合已能熟练使用 Data、Getter 等注解、想进一步探究其底层运作方式的中高级工程师。压缩包共 40 个文件约 88KB包含 9 个 java 源码、10 个 class 字节码、5 个 lst 与 1 个 processor 处理器文件另有 xml、iml、properties 等工程配置以及 dmn、bpmn 流程定义和 jar 依赖整体呈现一个多模块的注解处理实验工程。资源从注解处理器、预处理器元数据、ASM 字节码操作到 IDE 集成与自定义处理器逐层拆解并讨论了 final 字段、第三方库兼容性等使用限制。已有 665 人学习读者可借此对照源码理解 Lombok 如何在编译阶段插入方法、如何借助 ASM 改写字节码并掌握自定义注解处理器的实现思路为排查编译期问题与扩展注解能力提供参考。1. 从一行 Data 说起这个项目到底在折腾什么你有没有想过一个问题为什么在实体类上写一个Data编译完的 class 文件里就凭空多出了 getter、setter、equals、hashCode、toString源码里明明没有这些方法IDE 里却能点出来反射调用也能拿到。很多人用了好几年 Lombok把它当成“IDE 插件”或者“语法糖”但真到面试被问“Lombok 是怎么改字节码的”或者线上遇到 Lombok 和编译工具链打架时就说不清了。这份资源就是冲着这个黑匣子去的——它是一套用代码讲清 Lombok 实现原理的工程核心围绕注解处理器Annotation Processor和字节码操作两条线展开。适合两类人一类是天天用 Lombok 但想搞明白它底层怎么跑的开发者另一类是想自己写注解处理器、做编译期代码生成的工程师。读完你至少能自己动手写一个简化版的Getter知道 AST 在哪一步被改、class 文件在哪一步被写出来。2. 原理拆解注解处理器怎么在编译期“无中生有”2.1 先分清 Lombok 的两个身份很多人把 Lombok 理解成一个 IDE 插件这个认知只对了一半。Lombok 实际上同时扮演两个角色一个是编译期的注解处理器javac 的Processor另一个是 IDE 侧的插件让编辑器不报错、能补全。真正干活的是前者IDE 插件只是为了让你的编辑器别飘红。编译期这条链路是这样的javac 在解析完源码、生成抽象语法树AST之后会进入注解处理轮次annotation processing round。Lombok 注册的处理器在这个阶段被调用它拿到的是已经解析好的 AST 节点然后直接往这些节点上“挂”方法——注意不是生成新的源文件而是直接修改当前正在编译的 AST。这就是为什么 Lombok 不需要你手动再编译一次生成的文件它是在同一轮编译里把方法塞进去的。这里有个关键点标准的注解处理器继承AbstractProcessor只能生成新文件不能改已有的类。Lombok 能改是因为它用了内部 APIcom.sun.tools.javac包下的东西直接操作 AST。这也是为什么 Lombok 对 JDK 版本这么敏感——JDK 9 模块化之后这些内部包默认不开放得加--add-opens或者--add-exports才能跑。2.2 一个最小注解处理器的骨架要理解 Lombok先得能写出一个最普通的注解处理器。下面这段代码是一个能跑的最小骨架它不干别的只是在编译期打印出被注解的元素名字// 最小注解处理器继承 AbstractProcessor注册支持的注解 SupportedAnnotationTypes(com.example.demo.MyAnnotation) SupportedSourceVersion(SourceVersion.RELEASE_8) public class SimpleProcessor extends AbstractProcessor { Override public boolean process(Set? extends TypeElement annotations, RoundEnvironment roundEnv) { // roundEnv 里能拿到所有被 MyAnnotation 标记的元素 for (Element element : roundEnv.getElementsAnnotatedWith( processingEnv.getElementUtils().getTypeElement(com.example.demo.MyAnnotation))) { // 这里只是打印真正的 Lombok 会在这里改 AST System.out.println(被注解的元素: element.getSimpleName()); } return true; // 返回 true 表示这个注解已被处理不再往下传 } }逻辑说明process方法是注解处理器的入口javac 每一轮注解处理都会调它。roundEnv.getElementsAnnotatedWith返回所有被目标注解标记的元素元素可能是类、方法、字段。参数annotations是这一轮要处理的注解集合roundEnv是当前轮次的环境能拿到根元素和工具类。关键参数SupportedAnnotationTypes声明这个处理器关心哪些注解写全限定名SupportedSourceVersion声明支持的源码版本写低了会有警告。返回值true表示“这个注解我处理了别的处理器别再处理”返回false则继续传递。这个骨架跑起来需要在META-INF/services/javax.annotation.processing.Processor文件里注册处理器全类名否则 javac 根本不知道它的存在。Lombok 也是这么注册的只不过它注册的处理器内部逻辑复杂得多。2.3 Lombok 改 AST 的核心动作Lombok 的处理器拿到 AST 节点后核心动作是往类节点上添加方法节点。简化后的逻辑大致是这样// 伪代码Lombok 内部往类节点挂 getter 的简化逻辑 public boolean process(Set? extends TypeElement annotations, RoundEnvironment roundEnv) { for (Element element : roundEnv.getElementsAnnotatedWith(Getter.class)) { if (element.getKind() ElementKind.FIELD) { VariableElement field (VariableElement) element; TypeElement clazz (TypeElement) field.getEnclosingElement(); // 拿到 javac 内部的类声明节点 JavacNode classNode JavacAST.of(clazz); // 构造 getter 方法名get 首字母大写字段名 String methodName get capitalize(field.getSimpleName().toString()); // 用 MethodDeclaration 构造方法节点挂到类节点上 classNode.addMethod(methodName, Modifier.PUBLIC, field.asType(), return this. field.getSimpleName() ;); } } return true; }逻辑说明这段是简化后的伪代码真实 Lombok 用的是JavacTreeMaker和JavacNode这套封装。核心思路是遍历被Getter标记的字段找到它所属的类然后构造一个方法声明节点方法体是return this.字段名最后把这个方法节点加到类节点的方法列表里。javac 后续生成字节码时会把这个新加的方法一起编译进去。参数说明field.asType()拿到字段的类型作为 getter 的返回类型Modifier.PUBLIC是方法修饰符方法体字符串会被解析成 AST 表达式。真实实现里还要处理布尔类型is前缀、静态字段、访问权限等边界情况。提示Lombok 改 AST 用的是 javac 内部 API不同 JDK 版本内部结构会变所以 Lombok 每个大版本都要适配新 JDK。这也是为什么升级 JDK 时经常要同步升 Lombok。3. 跑起来从零编译一个简化版 Lombok3.1 环境准备和项目结构要复现这套原理不需要真的去读 Lombok 全部源码可以自己搭一个简化工程。环境要求JDK 8 或 11JDK 8 对内部 API 限制少适合入门Maven 3.6。项目结构建议这样组织lombok-demo/ ├── pom.xml ├── src/main/java/ │ ├── com/example/annotation/ │ │ └── MyGetter.java # 自定义注解 │ ├── com/example/processor/ │ │ └── MyGetterProcessor.java # 注解处理器 │ └── com/example/app/ │ └── User.java # 使用注解的实体类 └── src/main/resources/ └── META-INF/services/ └── javax.annotation.processing.Processorpom.xml里关键是把处理器和业务代码分开编译处理器本身不能依赖 Lombok否则会循环。常见做法是用两个 module或者用maven-compiler-plugin的annotationProcessorPaths配置。3.2 自定义注解和处理器实现先定义注解// MyGetter.java自定义注解对标 Lombok 的 Getter Target(ElementType.FIELD) // 只能标在字段上 Retention(RetentionPolicy.SOURCE) // 只在源码期保留编译后消失 public interface MyGetter { }Retention(SOURCE)是关键Lombok 的注解也是 SOURCE 级别编译完就没了所以运行时反射拿不到注解但方法已经生成好了。处理器实现// MyGetterProcessor.java处理 MyGetter生成 getter 方法 SupportedAnnotationTypes(com.example.annotation.MyGetter) SupportedSourceVersion(SourceVersion.RELEASE_8) public class MyGetterProcessor extends AbstractProcessor { Override public boolean process(Set? extends TypeElement annotations, RoundEnvironment roundEnv) { for (Element element : roundEnv.getElementsAnnotatedWith(MyGetter.class)) { if (element.getKind() ! ElementKind.FIELD) continue; VariableElement field (VariableElement) element; TypeElement clazz (TypeElement) field.getEnclosingElement(); String fieldName field.getSimpleName().toString(); String methodName get Character.toUpperCase(fieldName.charAt(0)) fieldName.substring(1); // 用 JavaPoet 或直接拼字符串生成方法源码 String methodCode public field.asType() methodName () { return this. fieldName ; }; try { // 把生成的方法写进当前类 JavaFileObject file processingEnv.getFiler() .createSourceFile(clazz.getQualifiedName() Getter); try (Writer writer file.openWriter()) { writer.write(package processingEnv.getElementUtils() .getPackageOf(clazz) ;\n); writer.write(public class clazz.getSimpleName() Getter {\n methodCode \n}); } } catch (IOException e) { processingEnv.getMessager().printMessage( Diagnostic.Kind.ERROR, 生成失败: e.getMessage()); } } return true; } }逻辑说明这段代码演示的是标准注解处理器的做法——生成一个新文件。注意它和 Lombok 的区别Lombok 是直接改原类的 AST而标准处理器只能生成新文件。这里生成一个UserGetter类里面放着 getter 方法。虽然效果不如 Lombok 优雅但能帮你理解注解处理器的基本流程。参数说明processingEnv.getFiler()是生成文件的工具createSourceFile创建新的源文件processingEnv.getMessager()用来在编译期报错或警告比System.out更规范IDE 能直接定位到出错的行。注册文件META-INF/services/javax.annotation.processing.Processor内容就一行com.example.processor.MyGetterProcessor3.3 编译验证和结果查看在User.java里用上注解// User.java使用自定义注解 public class User { MyGetter private String name; MyGetter private int age; }执行mvn clean compile编译完成后去target/classes/com/example/app/目录下看会多出一个UserGetter.class。用javap -p UserGetter.class反编译能看到生成的方法javap -p target/classes/com/example/app/UserGetter.class # 输出里能看到 public java.lang.String getName(); 和 public int getAge();这一步跑通你就理解了注解处理器“生成代码”的基本套路。接下来要理解 Lombok 的“改 AST”套路需要引入tools.jarJDK 8或者用--add-exports开放内部包JDK 9然后调用com.sun.tools.javac.tree.TreeMaker去构造方法节点。这部分代码量较大资源里给了完整的可运行版本建议直接跑一遍再对照改。注意JDK 9 以上跑内部 API 需要加 JVM 参数比如--add-exports jdk.compiler/com.sun.tools.javac.treeALL-UNNAMED否则会报IllegalAccessError。这是新手最容易翻车的地方。4. 避坑排查Lombok 和注解处理器常见的五个坑4.1 编译报错“找不到符号”但 IDE 不飘红现象命令行mvn compile报cannot find symbol: method getName()但 IDE 里代码是正常的点进去也能看到方法。原因IDE 装了 Lombok 插件它自己模拟了一套方法补全但命令行编译时注解处理器没生效。常见于 Maven 配置里annotationProcessorPaths没写或者 Lombok 版本和 JDK 版本不匹配。解决检查pom.xml里maven-compiler-plugin是否配置了annotationProcessorPaths指向 Lombok确认 Lombok 版本支持当前 JDK比如 JDK 17 需要 Lombok 1.18.22 以上。命令行执行mvn dependency:tree看 Lombok 有没有被正确引入。4.2 JDK 升级后 Lombok 直接罢工现象项目从 JDK 8 升到 JDK 17编译报java.lang.NoSuchFieldError或者IllegalAccessError指向com.sun.tools.javac包。原因Lombok 依赖 javac 内部 APIJDK 9 模块化后这些包默认不导出JDK 版本越高内部结构变化越大老版本 Lombok 找不到对应的字段或方法。解决升级 Lombok 到支持目标 JDK 的版本这是最省事的做法。如果因为依赖锁定不能升就得在maven-compiler-plugin里加--add-exports和--add-opens参数把jdk.compiler相关包开放出来。血泪经验是升级 JDK 前先查 Lombok 的兼容性矩阵别等编译挂了才回头找。4.3 注解处理器生成了文件但没被编译现象自定义处理器跑完target/generated-sources下能看到生成的文件但最终 class 里没有对应的方法。原因生成的文件没有被加入编译源路径。Maven 默认会把target/generated-sources/annotations加进去但如果你手动改了sourceDirectory或者用了非标准目录就可能漏掉。解决检查pom.xml里有没有build-helper-maven-plugin把生成目录加进 source root或者确认处理器用的是createSourceFile而不是createResource。生成源文件用createSourceFile生成资源用createResource用错了就不会被编译。4.4 处理器里抛异常导致整个编译失败现象编译时突然报一堆java.lang.NullPointerException堆栈指向处理器内部业务代码一行没改。原因处理器在process方法里没做空判断比如element.getEnclosingElement()返回 null 时直接强转或者processingEnv.getFiler()重复创建同名文件抛FilerException。解决处理器里所有从 AST 拿到的元素都要判空生成文件前先检查是否已存在或者用createSourceFile时捕获FilerException并忽略。更规范的做法是用Messager报错而不是直接抛异常这样 IDE 能定位到具体代码行。4.5 增量编译时处理器不触发现象改了实体类重新编译发现生成的代码没更新还是旧的。原因Maven 增量编译判断源文件没变就不重新跑注解处理器但处理器依赖的注解或配置变了它检测不到。解决执行mvn clean compile强制全量编译。如果项目大、全量慢可以在maven-compiler-plugin里配置useIncrementalCompilationfalse或者用mvn compile -Dmaven.compiler.useIncrementalCompilationfalse。我一般会在 CI 里强制 clean本地开发才用增量。5. 二次开发把原理变成自己的代码生成器理解了 Lombok 的 AST 操作之后最有价值的二次开发方向是写自己的编译期代码生成器。比如你团队里有一套重复的 DTO 转换逻辑每次加字段都要手动改 Converter这种活完全可以交给注解处理器。改造思路分三步。第一步定义注解比如AutoConverter标在 DTO 类上声明目标类型。第二步写处理器在process里拿到被注解的类读取它的字段列表生成一个XxxConverter类里面是字段到字段的赋值代码。第三步注册处理器并配置到构建流程里。这里给一个生成 Converter 的核心片段// 读取源类字段生成转换方法 TypeElement source (TypeElement) element; List? extends Element fields source.getEnclosedElements().stream() .filter(e - e.getKind() ElementKind.FIELD) .collect(Collectors.toList()); StringBuilder body new StringBuilder(); body.append(public static ).append(targetType).append( convert() .append(source.getSimpleName()).append( src) {\n); body.append( ).append(targetType).append( dst new ).append(targetType).append(();\n); for (Element f : fields) { String name f.getSimpleName().toString(); // 生成 dst.setXxx(src.getXxx()) 这样的赋值 body.append( dst.set).append(capitalize(name)) .append((src.get).append(capitalize(name)).append(());\n); } body.append( return dst;\n});逻辑说明这段代码遍历源类的所有字段为每个字段生成一行 setter 调用。capitalize是首字母大写的工具方法。生成的类是一个静态工具类调用方直接XxxConverter.convert(src)就能完成转换。参数说明targetType是目标类的全限定名可以从注解的属性里读字段过滤要排除静态字段和serialVersionUID这类特殊字段否则生成的代码会编译不过。验证方法写一个单元测试构造源对象调用生成的 Converter断言目标对象的字段值一致。更彻底的做法是用反射遍历所有字段确保没有遗漏。我一般会加一个测试用例字段数量对不上就 fail这样加字段忘了改注解能立刻发现。改造时有个技巧别一上来就追求支持所有类型。先支持基本类型和 String跑通了再逐步加 List、Map、嵌套对象。嵌套对象的转换可以递归生成但要注意循环引用加个已处理集合去重。另外生成的代码要加Generated注解javax.annotation.Generated标明是自动生成的方便后续排查问题时区分。从那以后我每次写注解处理器都会先写一个最小可运行版本确认process被调用了、文件生成了、编译通过了再往上加逻辑。这个习惯帮我省了无数个对着空输出发呆的下午。希望帮到你。本文还有配套的精品资源点击获取

相关新闻

3060 12GB本地部署DeepSeek-OCR2:量化与显存优化实战

3060 12GB本地部署DeepSeek-OCR2:量化与显存优化实战

把 DeepSeek-OCR2 塞进一张 3060 显卡,听起来像是个挺冒险的决定——毕竟大家聊到本地部署大模型,第一反应都是"24GB 显存起步"。但如果你手头刚好只有一张 3060(尤其是 12GB 显存版),又不想把合同、票据、私…

2026/10/16 10:38:36 阅读更多 →
智能体接口标准实战:Tool-Calling、OpenAPI 与 MCP 如何协同

智能体接口标准实战:Tool-Calling、OpenAPI 与 MCP 如何协同

如果你从“智能的解构”这个系列一路读过来,大概率已经对 Agent、RAG、工作流这些概念不陌生了。但到了第 11 章,我想先把注意力从模型本身挪开,放回连接模型的那些接口:Tool-Calling、OpenAPI、MCP。这三样东西看起来像三件互不相…

2026/10/16 10:38:36 阅读更多 →
用Python将Obsidian笔记库向量化,搭建个人AI知识库实战

用Python将Obsidian笔记库向量化,搭建个人AI知识库实战

大概两三个月前,我的 Obsidian 笔记库突破 4000 个 Markdown 文件之后,第一个撑不住的不是 Obsidian 本身,而是“检索”这个动作。过去用标题搜索、全文搜索还能勉强定位,可当笔记之间互相引用、标签层层嵌套、还混着大量从文档里…

2026/10/17 11:52:39 阅读更多 →

最新新闻

动态规划入门实战:六道经典题吃透状态、转移与边界

动态规划入门实战:六道经典题吃透状态、转移与边界

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/17 13:16:24 阅读更多 →
AI PR门禁实践:基于GitHub Actions与大模型的代码审查自动化

AI PR门禁实践:基于GitHub Actions与大模型的代码审查自动化

1. 先搞清楚:传统 CI 卡不住的那些问题 先说个很多团队都遇到过的场景:PR 提交上来,流水线亮绿灯——编译过了、单测过了、覆盖率没跌、Lint 也没报错,看起来一切正常。结果人工 review 的时候发现,整个 PR 只是把某个…

2026/10/17 13:16:24 阅读更多 →
用 Deep Agents 构建生产级 Agent Harness:基于 LangGraph+LangChain 的长周期智能体实践与 TaoToken 接入

用 Deep Agents 构建生产级 Agent Harness:基于 LangGraph+LangChain 的长周期智能体实践与 TaoToken 接入

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/17 13:16:24 阅读更多 →
深度学习GPU环境排查:cuDNN卷积算法获取失败报错的解决方案

深度学习GPU环境排查:cuDNN卷积算法获取失败报错的解决方案

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/17 13:16:24 阅读更多 →
物联网+区块链四大落地方向:设备可信、轻量存证、协同治理与隐私增强

物联网+区块链四大落地方向:设备可信、轻量存证、协同治理与隐私增强

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/17 13:16:24 阅读更多 →
Django电商性能优化:FastDFS、页面静态化与Redis缓存实战

Django电商性能优化:FastDFS、页面静态化与Redis缓存实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/17 13:15:23 阅读更多 →

日新闻

DeepSeek选型与部署:V3/R1、Ollama、API全攻略

DeepSeek选型与部署:V3/R1、Ollama、API全攻略

简介:《DeepSeek使用方法.pdf》是一份面向DeepSeek入门及进阶用户的完整使用指南,重点围绕V3与R1两款模型的能力差异与适用场景展开,帮助读者根据任务类型与成本选择合适的模型。资源共1个PDF文件,压缩包大小约311KB,篇…

2026/10/17 0:00:25 阅读更多 →
200+Deepseek润色指令拆解:从底层原理到场景落地的完整指南

200+Deepseek润色指令拆解:从底层原理到场景落地的完整指南

简介:这是一份聚焦DeepSeek提示词优化的《200Deepseek润色指令》PDF文档,共收录两百余条可直接套用的润色指令,涵盖语法修正、风格统一、逻辑梳理、表达精炼等维度,并针对商务写作、学术论文、广告文案等场景给出差异化建议。文档…

2026/10/17 0:00:25 阅读更多 →
OpenCV轮廓法物体计数系统:轻量、可控、可落地的工业级实现

OpenCV轮廓法物体计数系统:轻量、可控、可落地的工业级实现

简介:本资源是一份基于OpenCV的本科课程设计完整报告,面向计算机视觉初学者、图像处理学习者及高校通信/信息类专业学生,解决物体智能计数与检测结果结构化记录的实际问题。项目覆盖图像预处理、轮廓检测、边界框绘制、轨迹栏交互式参数调节、…

2026/10/17 0:00:25 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/16 21:35:51 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/17 1:44:59 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/16 15:04:24 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/16 21:54:38 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/16 3:49:43 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/16 14:23:36 阅读更多 →