手写极简Spring容器,深入理解IoC与AOP
正文一、前言很多开发只会使用 Spring 框架但完全搞不懂 IoC 控制反转、AOP 切面底层到底怎么运行。网上讲解源码门槛太高今天我们从零手写极简版迷你 Spring 容器只用 JDK 原生技术自定义注解、反射、动态代理实现核心功能组件扫描、单例 Bean 管理、自动依赖注入、方法日志切面增强。项目完全脱离 Spring 依赖纯原生 Java 实现看完就能彻底理解Spring 如何通过注解自动创建对象IoC 容器Autowired 自动注入的底层反射原理Component 扫描包的实现逻辑JDK 动态代理实现 AOP 前置 / 后置通知单例 Bean 缓存设计、容器启动完整流程适合 Java 进阶、面试突击 Spring 底层原理、课程实训作业。二、项目整体需求与架构2.1 核心功能需求注解驱动 Bean 管理自定义 Component 注解标记业务类容器自动扫描实例化无需手动 new单例全局缓存容器启动统一创建单例对象全局复用自动依赖注入自定义 Autowired通过反射给成员变量赋值解除硬编码耦合AOP 切面增强自定义 Aspect 标记切面类JDK 动态代理对目标方法前后添加日志不修改原有业务代码容器统一上下文入口一键启动扫描、创建 Bean、生成代理、获取实例。2.2 整体包分层结构com.example.ioc ├── annotation // 自定义注解 │ Component.java │ Autowired.java │ Aspect.java │ Scope.java ├── aop // AOP切面基础 │ BaseAspect.java │ AspectHandler.java ├── context // IoC容器核心 │ BeanDefinition.java │ BeanScanner.java │ BeanFactory.java │ AopProxyFactory.java │ MiniSpringContext.java ├── service // 业务接口实现 │ UserService.java │ OrderService.java │ impl │ UserServiceImpl.java │ OrderServiceImpl.java └── TestContainer // 启动测试类2.3 核心技术点梳理注解 反射运行时读取类上 Component、Autowired 注解动态创建对象、赋值成员变量单例模式BeanFactory 使用 ConcurrentHashMap 缓存单例保证线程安全工厂模式Bean 工厂负责对象创建代理工厂统一生成 AOP 代理JDK 动态代理实现 InvocationHandler 拦截方法完成切面增强IO 文件遍历包扫描器递归读取 class 文件加载 Class 对象泛型、函数式编程简化容器获取 Bean 逻辑。三、Maven 项目配置pom.xml 核心依赖?xml version1.0 encodingUTF-8? project xmlnshttp://maven.apache.org/POM/4.0.0 modelVersion4.0.0/modelVersion groupIdcom.example.ioc/groupId artifactIdmini-spring-ioc/artifactId version1.0-SNAPSHOT properties maven.compiler.source17/maven.compiler.source maven.compiler.target17/maven.compiler encodingUTF-8 /properties dependencies !-- Lombok简化实体代码 -- dependency groupIdorg.projectlombok/groupId artifactIdlombok/artifactId version1.18.38/version scopeprovided/scope /dependency !-- 日志依赖 -- dependency groupIdorg.slf4j/groupId artifactIdslf4j-api/artifactId version2.0.9/version /dependency dependency groupIdch.qos.logback/groupId artifactIdlogback-classic/artifactId version1.4.11/version /dependency !-- JUnit测试 -- dependency groupIdjunit/groupId artifactIdjunit/artifactId version4.13/version scopetest/scope /dependency /dependencies /project四、分层完整代码实现4.1 自定义注解层 annotation1. Component 标记容器管理 Beanpackage com.example.ioc.annotation; import java.lang.annotation.*; /** * 标记类为IoC容器管理组件 */ Target(ElementType.TYPE) Retention(RetentionPolicy.RUNTIME) Documented public interface Component { String value() default ; }2. Autowired 自动注入注解package com.example.ioc.annotation; import java.lang.annotation.*; /** * 字段自动依赖注入 */ Target(ElementType.FIELD) Retention(RetentionPolicy.RUNTIME) Documented public interface Autowired { }3. Scope 作用域注解package com.example.ioc.annotation; import java.lang.annotation.*; /** * Bean作用域默认singleton单例 */ Target(ElementType.TYPE) Retention(RetentionPolicy.RUNTIME) public interface Scope { String value() default singleton; }4. Aspect 切面注解package com.example.ioc.annotation; import java.lang.annotation.*; /** * 标记切面类value指定要代理的目标类全限定名 */ Target(ElementType.TYPE) Retention(RetentionPolicy.RUNTIME) public interface Aspect { String value() default ; }4.2 AOP 切面基础层 aop1. 切面基类 BaseAspectpackage com.example.ioc.aop; /** * 切面统一父类定义前后置通知规范 */ public abstract class BaseAspect { // 方法执行前增强 public abstract void before(); // 方法执行后增强 public abstract void after(); }2. 动态代理拦截器 AspectHandlerpackage com.example.ioc.aop; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; /** * JDK动态代理调用处理器拦截目标方法执行切面逻辑 */ public class AspectHandler implements InvocationHandler { // 原始目标对象 private final Object target; // 切面增强类 private final BaseAspect aspect; public AspectHandler(Object target, BaseAspect aspect) { this.target target; this.aspect aspect; } Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { // 前置通知 aspect.before(); // 执行原始业务方法 Object result method.invoke(target, args); // 后置通知 aspect.after(); return result; } /** 创建代理对象 */ public Object getProxy() { return java.lang.reflect.Proxy.newProxyInstance( target.getClass().getClassLoader(), target.getClass().getInterfaces(), this ); } }3. 日志切面实现类package com.example.ioc.aop; import com.example.ioc.annotation.Aspect; import com.example.ioc.annotation.Component; import lombok.extern.slf4j.Slf4j; /** * 日志切面拦截UserServiceImpl所有方法打印前后日志 */ Slf4j Component Aspect(value com.example.ioc.service.impl.UserServiceImpl) public class LogAspect extends BaseAspect{ Override public void before() { log.info(【AOP前置通知】方法即将执行); } Override public void after() { log.info(【AOP后置通知】方法执行完成); } }4.3 IoC 容器核心层 context1. BeanDefinition Bean 元数据模型package com.example.ioc.context; import com.example.ioc.annotation.Scope; import lombok.Getter; import lombok.Setter; /** * Bean定义存储类名、作用域、Bean标识名称 */ Getter Setter public class BeanDefinition { private String beanName; private Class? beanClass; private String scope singleton; public BeanDefinition(String beanName, Class? beanClass) { this.beanName beanClass; // 读取Scope注解 if (beanClass.isAnnotationPresent(Scope.class)) { this.scope beanClass.getAnnotation(Scope.class).value(); } } public boolean isSingleton() { return singleton.equals(scope); } }2. 包扫描器 BeanScannerpackage com.example.ioc.context; import com.example.ioc.annotation.Component; import java.io.File; import java.net.URL; import java.util.HashMap; import java.util.Map; /** * 包扫描工具递归遍历包下class文件识别Component生成BeanDefinition */ public class BeanScanner { private MapString, BeanDefinition beanDefinitionMap new HashMap(); public void scan(String basePackage) throws Exception { // 包路径转文件路径 String path basePackage.replace(., /); URL resource getClass().getClassLoader().getResource(path); if (resource null) return; File root new File(resource.toURI()); scanFile(root, basePackage); } // 递归扫描目录 private void scanFile(File file, String pkg) throws ClassNotFoundException { if (file.isDirectory()) { File[] files file.listFiles(); if (files null) return; for (File f : files) { if (f.isDirectory()) { scanFile(f, pkg . f.getName()); } else { String className pkg . f.getName().replace(.class, ); Class? clazz Class.forName(className); // 标记Component才注册 if (clazz.isAnnotationPresent(Component.class)) { registerBean(clazz); } } } } } // 注册Bean定义 private void registerBean(Class? clazz) { Component comp clazz.getAnnotation(Component.class); String beanName; if (comp.value().isBlank()) { // 首字母小写作为beanName String simpleName clazz.getSimpleName(); beanName Character.toLowerCase(simpleName.charAt(0)) simpleName.substring(1); // 去除Impl后缀 if (beanName.endsWith(Impl)) { beanName beanName.substring(0, beanName.length() - 4); } } else { beanName comp.value(); } beanDefinitionMap.put(beanName, new BeanDefinition(beanName, clazz)); } public MapString, BeanDefinition getBeanDefinitionMap() { return beanDefinitionMap; } }3. AOP 代理工厂 AopProxyFactorypackage com.example.ioc.context; import com.example.ioc.aop.AspectHandler; import com.example.ioc.aop.BaseAspect; import com.example.ioc.annotation.Aspect; /** * AOP代理单例工厂生成JDK动态代理对象 */ public class AopProxyFactory { private static final AopProxyFactory INSTANCE new AopProxyFactory(); private AopProxyFactory(){} public static AopProxyFactory getInstance() { return INSTANCE; } public Object createProxy(Class? aspectCls) throws Exception { // 实例化切面 BaseAspect aspect (BaseAspect) aspectCls.getDeclaredConstructor().newInstance(); // 获取切面指定的目标类 Aspect aspectAnno aspectCls.getAnnotation(Aspect.class); Class? targetCls Class.forName(aspectAnno.value()); Object target targetCls.getDeclaredConstructor().newInstance(); // 创建代理 AspectHandler handler new AspectHandler(target, aspect); return handler.getProxy(); } }4. Bean 工厂 BeanFactorypackage com.example.ioc.context; import com.example.ioc.annotation.Autowired; import java.lang.reflect.Field; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; /** * Bean工厂负责实例化、依赖注入、单例缓存、代理替换 */ public class BeanFactory { private static final BeanFactory INSTANCE new BeanFactory(); // 单例Bean缓存池线程安全 private final MapString, Object singletonObjects new ConcurrentHashMap(); private MapString, BeanDefinition beanDefinitionMap; private BeanFactory(){} public static BeanFactory getInstance() { return INSTANCE; } public void init(MapString, BeanDefinition map) { this.beanDefinitionMap map; } // 初始化所有单例原始Bean public void createSingletonBeans() throws Exception { for (BeanDefinition def : beanDefinitionMap.values()) { if (def.isSingleton() !singletonObjects.containsKey(def.getBeanName())) { Object bean def.getBeanClass().getDeclaredConstructor().newInstance(); singletonObjects.put(def.getBeanName(), bean); } } } // 自动依赖注入 public void injectBean() throws Exception { for (BeanDefinition def : beanDefinitionMap.values()) { Class? clazz def.getBeanClass(); Object bean clazz.getDeclaredConstructor().newInstance(); // 遍历所有字段处理Autowired Field[] fields clazz.getDeclaredFields(); for (Field field : fields) { if (field.isAnnotationPresent(Autowired.class)) { field.setAccessible(true); // 根据类型从缓存获取依赖Bean Object depBean getBeanByType(field.getType()); field.set(bean, depBean); } } singletonObjects.put(def.getBeanName(), bean); } } // 替换切面目标Bean为代理对象 public void replaceAopProxy() throws Exception { AopProxyFactory proxyFactory AopProxyFactory.getInstance(); for (BeanDefinition def : beanDefinitionMap.values()) { Class? clazz def.getBeanClass(); if (clazz.isAnnotationPresent(com.example.ioc.annotation.Aspect.class)) { Object proxy proxyFactory.createProxy(clazz); // 覆盖缓存中原对象 modifyBean(clazz, proxy); } } } // 根据类型获取Bean SuppressWarnings(unchecked) public T T getBeanByType(ClassT clazz) { for (Object bean : singletonObjects.values()) { if (clazz.isAssignableFrom(bean.getClass())) { return (T) bean; } } return null; } // 根据Bean名称获取实例 public Object getBean(String beanName) { return singletonObjects.get(beanName); } // 根据类型替换缓存中的Bean public void modifyBean(Class? targetCls, Object proxyBean) { for (Map.EntryString, Object entry : singletonObjects.entrySet()) { if (targetCls.isAssignableFrom(entry.getValue().getClass())) { singletonObjects.put(entry.getKey(), proxyBean); } } } public MapString, Object getSingletonObjects() { return singletonObjects; } }5. 容器上下文 MiniSpringContextpackage com.example.ioc.context; import lombok.extern.slf4j.Slf4j; /** * IoC容器统一入口单例全局上下文 */ Slf4j public class MiniSpringContext { private static MiniSpringContext INSTANCE; private final String basePackage; private final BeanScanner scanner; private final BeanFactory beanFactory; private MiniSpringContext(String basePackage) { this.basePackage basePackage; this.scanner new BeanScanner(); this.beanFactory BeanFactory.getInstance(); refresh(); } // 容器刷新核心流程扫描-创建Bean-注入依赖-生成AOP代理 private void refresh() { try { log.info(迷你IoC容器开始启动...); // 1.包扫描 scanner.scan(basePackage); // 2.初始化工厂 beanFactory.init(scanner.getBeanDefinitionMap()); // 3.创建原始单例 beanFactory.createSingletonBeans(); // 4.自动依赖注入 beanFactory.injectBean(); // 5.替换AOP代理对象 beanFactory.replaceAopProxy(); log.info(IoC容器启动完成); } catch (Exception e) { log.error(容器启动失败, e); } } // 获取容器单例 public static MiniSpringContext getInstance(String basePackage) { if (INSTANCE null) { synchronized (MiniSpringContext.class) { if (INSTANCE null) { INSTANCE new MiniSpringContext(basePackage); } } } return INSTANCE; } // 根据类型获取Bean public T T getBean(ClassT clazz) { return beanFactory.getBeanByType(clazz); } // 根据Bean名称获取 public Object getBean(String beanName) { return beanFactory.getBean(beanName); } }4.4 业务层 Service1. UserService 接口package com.example.ioc.service; public interface UserService { void sayHello(); }2. UserServiceImpl 实现类被 AOP 拦截package com.example.ioc.service.impl; import com.example.ioc.annotation.Component; import com.example.ioc.service.User; Component public class UserServiceImpl implements UserService { Override public void sayHello() { System.out.println(用户业务方法执行Hello IoCAOP); } }3. OrderService 接口package com.example.ioc.service; public interface OrderService { void testOrder(); }4. OrderServiceImpl依赖注入 UserServicepackage com.example.ioc.service.impl; import com.example.ioc.annotation.Autowired; import com.example.ioc.annotation.Component; import com.example.ioc.service.OrderService; import com.example.ioc.service.UserService; Component public class OrderServiceImpl implements OrderService { Autowired private UserService userService; Override public void testOrder() { System.out.println(订单业务逻辑执行); userService.sayHello(); } }4.5 测试启动类package com.example.ioc; import com.example.ioc.context.MiniSpringContext; import com.example.ioc.service.OrderService; import lombok.extern.slf4j.Slf4j; Slf4j public class TestContainer { public static void main(String[] args) { // 扫描根包启动容器 MiniSpringContext context MiniSpringContext.getInstance(com.example.ioc); // 根据类型获取Bean Order order1 context.getBean(OrderService.class); // 根据名称获取Bean Order order2 (OrderService) context.getBean(orderService); log.info(order1和order2是否为同一个单例{}, order1 order2); log.info(执行业务方法观察AOP日志); order1.testOrder(); } }五、运行结果解析控制台输出流程容器启动日志完成包扫描、Bean 实例化、依赖注入打印两个 OrderService 对象地址完全相同证明单例缓存生效执行 testOrder () 方法 先打印【AOP 前置通知】再输出订单业务调用 userService.sayHello 后打印【AOP 后置通知】自动注入成功OrderServiceImpl 中无需手动 new UserService容器自动装配。六、底层核心原理拆解面试高频1. IoC 控制反转传统写法业务代码主动 new 依赖对象主动创建 IoC 容器由容器统一创建所有 Bean业务直接获取控制权交给容器反转 本项目通过包扫描 反射动态创建对象完全模拟 Spring 的 Bean 工厂。2. Autowired 注入原理反射获取类所有 Field 字段判断字段标注 Autowired根据字段类型去单例缓存池中匹配对应 BeansetAccessible (true) 打破私有权限反射赋值实现自动装配。3. AOP JDK 动态代理限制JDK 动态代理只能代理实现接口的类原理运行时生成目标接口的代理类拦截所有接口方法 如果类没有实现接口需要 CGLIB 字节码代理本项目为简化使用 JDK 代理。4. 单例线程安全设计BeanFactory 使用 ConcurrentHashMap 存储单例容器创建使用双重校验锁实现单例上下文避免多线程启动容器创建多个上下文实例。七、结尾这份迷你 Spring 容器项目没有任何 Spring 框架依赖全部基于 Java 基础注解、反射、动态代理、单例、工厂模式手写实现完美复刻 Spring 两大核心 IoC 和 AOP。很多开发者只会调 Autowired、Aspect 注解但完全不知道底层如何反射创建对象、如何拦截方法跟着本项目逐行调试就能打通 Spring 底层知识盲区面试问到 IoC/AOP 手写实现也能流畅作答。

相关新闻

本地大语言模型部署与应用实践:从Ollama到RAG场景构建

本地大语言模型部署与应用实践:从Ollama到RAG场景构建

本地大语言模型(LLM)正在从云端走向个人设备,成为开发者、研究者和技术爱好者手中的新工具。当模型参数从百亿级压缩到数十亿甚至几亿,当推理速度从秒级提升到毫秒级,我们不再只是调用一个远程API,而是真正…

2026/8/18 10:16:04 阅读更多 →
千兆以太网滑环速率测试:原理、方法与工程实践指南

千兆以太网滑环速率测试:原理、方法与工程实践指南

千兆以太网滑环速率测试:当高速网络遇上旋转连接,如何确保数据不“打滑”? 如果你正在设计一个需要360度连续旋转的工业设备,比如风力发电机的机舱、旋转摄像头、雷达天线或者自动化生产线上的旋转工作台,那么你一定遇…

2026/8/18 10:16:04 阅读更多 →
产品需求收集与定位:从用户痛点挖掘到产品战略锚定

产品需求收集与定位:从用户痛点挖掘到产品战略锚定

1. 从“拍脑袋”到“有章法”:为什么需求收集是产品成败的起点 做产品,最怕的不是技术实现不了,而是吭哧吭哧做出来,发现没人用。这种挫败感,很多产品经理和创业者都经历过。问题出在哪?十有八九&#xff0…

2026/8/18 10:16:04 阅读更多 →

最新新闻

内网靶场虚拟环境搭建CFS

内网靶场虚拟环境搭建CFS

环境下载 通过网盘分享的文件:CFS三层靶机环境 链接: CFS三层靶机环境 提取码: 39y7 环境安装 按照上一步下载文件,每个文件夹对应一个独立的靶机 Target1_CentOS7 Target2_Ubuntu Target3_Windows7 在D盘下建立文件夹如下,用来存放导入的文件 下面以Target1_CentOS7为例,点…

2026/8/18 10:48:55 阅读更多 →
从零搭建RAG系统:基于LangChain与Chroma的本地知识库问答实战

从零搭建RAG系统:基于LangChain与Chroma的本地知识库问答实战

大家好,我是专注于技术实战分享的博主。在探索大模型应用落地的过程中,你是否遇到过这样的困境:模型回答看似流畅,但内容经常“一本正经地胡说八道”,缺乏对特定领域知识的精准把握?或者,当你想…

2026/8/18 10:48:55 阅读更多 →
【安卓逆向】为什么用Frida?

【安卓逆向】为什么用Frida?

在 Android 逆向分析中,JADX 和 Frida 通常是配合使用的。静态分析阶段主要使用 JADX,通过反编译 APK 查看 Java / Kotlin 代码,搜索关键类、方法、字符串以及加密、网络通信等相关逻辑。而当我们需要进一步观察程序在运行时的真实行为时&…

2026/8/18 10:48:55 阅读更多 →
夏秋技术充电:8周学习计划,从云原生到AI工程化的高效成长路径

夏秋技术充电:8周学习计划,从云原生到AI工程化的高效成长路径

1. 活动背景与核心价值:为什么要在夏秋之交做技术学习?每年到了8、9月份,对于很多技术人来说,都是一个微妙的“窗口期”。年初立下的Flag可能已经半途而废,而年底的绩效冲刺和项目复盘还没开始。这段时间,项…

2026/8/18 10:48:55 阅读更多 →
鸣潮刷到怀疑人生?把重复劳动交给ok-ww自动化工具,每天省出两小时

鸣潮刷到怀疑人生?把重复劳动交给ok-ww自动化工具,每天省出两小时

鸣潮刷到怀疑人生?把重复劳动交给ok-ww自动化工具,每天省出两小时 【免费下载链接】ok-wuthering-waves 鸣潮 后台自动战斗 自动刷声骸 一键日常 Automation for Wuthering Waves 项目地址: https://gitcode.com/GitHub_Trending/ok/ok-wuthering-wave…

2026/8/18 10:48:54 阅读更多 →
拯救硬盘:清理 Rust 及其他语言项目的构建目录

拯救硬盘:清理 Rust 及其他语言项目的构建目录

特别声明:本博客长期遭受 51CTO 盗文、剽窃,反复投诉,对方置若罔闻,行为非常可耻,你的优质文章也极有可能已被 51CTO 盗用,详情参见《51CTO,一个抄袭剽窃的流氓网站!》:https://laurence.blog.csdn.net/article/details/162671992,本文多处嵌入此声明,盗用此文即传播…

2026/8/18 10:47:54 阅读更多 →

日新闻

告别逐帧截图:用 extract-video-ppt 快速提取视频中的 PPT 并一键导出 PDF

告别逐帧截图:用 extract-video-ppt 快速提取视频中的 PPT 并一键导出 PDF

告别逐帧截图:用 extract-video-ppt 快速提取视频中的 PPT 并一键导出 PDF 【免费下载链接】extract-video-ppt extract the ppt in the video 项目地址: https://gitcode.com/gh_mirrors/ex/extract-video-ppt 如果你还停留在"看网课 不停暂停 截图 …

2026/8/18 0:00:57 阅读更多 →
思源宋体TTF一站式上手:7个字重免费商用,从下载到上线的完整走查

思源宋体TTF一站式上手:7个字重免费商用,从下载到上线的完整走查

思源宋体TTF一站式上手:7个字重免费商用,从下载到上线的完整走查 【免费下载链接】source-han-serif-ttf Source Han Serif TTF 项目地址: https://gitcode.com/gh_mirrors/so/source-han-serif-ttf 你是不是也经历过这种时刻:设计稿里…

2026/8/18 0:00:58 阅读更多 →
华硕笔记本控制权回收指南:GHelper 如何用一个 10MB 文件替代 Armoury Crate

华硕笔记本控制权回收指南:GHelper 如何用一个 10MB 文件替代 Armoury Crate

华硕笔记本控制权回收指南:GHelper 如何用一个 10MB 文件替代 Armoury Crate 【免费下载链接】g-helper Lightweight Armoury Crate alternative for Asus laptops with nearly the same functionality. Works with ROG Zephyrus, Flow, TUF, Strix, Scar, ProArt, …

2026/8/18 0:00:59 阅读更多 →

周新闻

基于阿里云与通义千问(Qwen)构建AI应用:从模型调用到生产部署的完整实践指南

基于阿里云与通义千问(Qwen)构建AI应用:从模型调用到生产部署的完整实践指南

如果你是一名开发者,最近可能已经感受到了AI大模型正在从“玩具”变成“生产力工具”的强烈信号。从代码补全到智能Agent,从本地部署到云端API,我们正处在一个技术栈快速重构的节点。然而,面对层出不穷的模型、框架和工具&#xf…

2026/8/18 9:15:35 阅读更多 →
工业通信系统底层逻辑:04 反射——高频能量撞墙之后会发生什么?

工业通信系统底层逻辑:04 反射——高频能量撞墙之后会发生什么?

第四篇:反射——高频能量撞墙之后会发生什么? —— 你以为信号已经过去了,其实它正在回来打你 老Q的现场笔记 第五季,我们正式进入工业神经系统层。这里不再是单个设备的战斗,而是整个工厂“经脉”层面的秩序之战。从这一篇开始,你将第一次看清:看似简单的信号传播,背…

2026/8/18 9:06:28 阅读更多 →
【文章复现】非线性值迭代自适应动态规划(ADP):离散时间非线性系统的策略迭代自适应动态规划算法研究附Matlab代码

【文章复现】非线性值迭代自适应动态规划(ADP):离散时间非线性系统的策略迭代自适应动态规划算法研究附Matlab代码

✅作者简介:热爱科研的Matlab仿真开发者,擅长毕业设计辅导、数学建模、数据处理、建模仿真、程序设计、完整代码获取、论文复现及科研仿真。🍎 往期回顾关注个人主页:Matlab科研工作室👇 关注我领取海量matlab电子书和…

2026/8/18 9:04:56 阅读更多 →

月新闻

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南 【免费下载链接】BaiduNetdiskPlugin-macOS For macOS.百度网盘 破解SVIP、下载速度限制~ 项目地址: https://gitcode.com/gh_mirrors/ba/BaiduNetdiskPlugin-macOS 还在为百度网盘macOS版的龟速下…

2026/8/17 18:54:37 阅读更多 →
终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换

终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换

终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换 【免费下载链接】ncmdump 项目地址: https://gitcode.com/gh_mirrors/ncmd/ncmdump 还在为网易云音乐下载的NCM格式文件无法在其他播放器播放而烦恼吗?ncmdump解密工具帮你轻松解决这个困…

2026/8/17 18:55:16 阅读更多 →
HarmonyOS 应用开发《掌上英语》第81篇: 智能体卡片:为英语学习 App 打造桌面级学习助手

HarmonyOS 应用开发《掌上英语》第81篇: 智能体卡片:为英语学习 App 打造桌面级学习助手

AgentCard 智能体卡片:为英语学习 App 打造桌面级学习助手适用平台:HarmonyOS 7.0 (API 26 Beta)一、引言 HarmonyOS 7.0(API 26 Beta)新增了 AgentCard 智能体卡片能力,这是继 HMAF(鸿蒙智能体框架&#x…

2026/8/17 18:55:55 阅读更多 →