比 MQ 更轻的异步方案:Spring 内置的这个隐藏功能,很多人还不知道

MySQL事务从原理到实战:ACID、MVCC、锁与Spring事务全解析 在数据库系统中,事务是保证数据一致性的核心机制,它解决的是并发场景下多个操作交错执行时的正确性问题。理解事务,首先要掌握其ACID特性及其底层实现:redo log确保持久性,undo log支撑回滚和多版本并发控制(MVCC),binlog与redo log的两阶段提交则保障主从数据一致。隔离级别定义了并发事务的可见性规则,MySQL InnoDB通过MVCC和间隙锁在Repeatable Read下处理幻读,同时行锁与间隙锁的组合也带来了死锁风险。实践层面,Spring的声明式事务简化了开发,但自调用、 阅读详情

👉 这是一个或许对你有用的社群

🐱 一对一交流/面试小册/简历优化/求职解惑,欢迎加入「芋道快速开发平台」知识星球。下面是星球提供的部分资料: 

👉这是一个或许对你有用的开源项目

国产Star破10w的开源项目,前端包括管理后台、微信小程序,后端支持单体、微服务架构

RBAC权限、数据权限、SaaS多租户、商城、支付、工作流、大屏报表、ERP、CRM、AI大模型、IoT物联网等功能:

  • 多模块:https://gitee.com/zhijiantianya/ruoyi-vue-pro

  • 微服务:https://gitee.com/zhijiantianya/yudao-cloud

  • 视频教程:https://doc.iocoder.cn

【国内首批】支持 JDK17/21+SpringBoot3、JDK8/11+Spring Boot2双版本 


问题:越写越胖的 Service 方法

工作年头长了,见过太多这样的 Service 方法:

public void createOrder(Order order) {
    // 1. 保存订单
    orderDao.save(order);
    // 2. 发送短信通知
    smsService.sendOrderConfirm(order.getUserPhone(), order.getId());
    // 3. 更新用户积分
    pointService.addPoints(order.getUserId(), order.getTotalAmount());
    // 4. 记录操作日志
    auditService.log("CREATE_ORDER", order.getId());
    // 5. 推送站内消息
    notifyService.push(order.getUserId(), "您的订单已提交");
    // 6. 触发风控检查
    riskService.check(order);
}

技术上没 Bug,跑得也好好的。但有一天产品说"下单后还要同步购物车",你得改;运营说"VIP 下单要额外赠券",你还得改。核心下单逻辑就这样被各种非核心需求越填越厚,所有依赖硬编码在一起。哪天 riskService 挂了,整个下单都跟着挂 ——这明显不合理。

很多人的第一反应是上 MQ。但如果是单体应用,或者只是同 JVM 内的逻辑解耦 ,部署一套 MQ 中间件有点杀鸡用牛刀。

Spring 早就提供了一套轻量级事件驱动机制 ——ApplicationEvent + @EventListener,本质是发布-订阅 模式,零额外依赖,Spring Boot 开箱即用。

基于 Spring Boot + MyBatis Plus + Vue & Element 实现的后台管理系统 + 用户小程序,支持 RBAC 动态权限、多租户、数据权限、工作流、三方登录、支付、短信、商城等功能

  • 项目地址:https://github.com/YunaiV/ruoyi-vue-pro

  • 视频教程:https://doc.iocoder.cn/video/

四个核心角色

Spring事件机制核心组件全景:事件、发布者、广播器、监听者四大角色的关系图

1. ApplicationEvent(事件)

数据载体。继承自 JDK EventObject,包含 source 和 timestamp。Spring 4.2 后支持发布任意对象(不继承也行),内部自动封装为 PayloadApplicationEvent。

2. ApplicationEventPublisher(发布者)

只有一个方法 publishEvent()。ApplicationContext 实现了这个接口,注入 ApplicationEventPublisher 更优雅——依赖接口而非实现 。

3. ApplicationEventMulticaster(广播器)

整个机制的核心调度引擎 。维护所有已注册的监听器列表,负责将事件分发给匹配的监听者。默认实现 SimpleApplicationEventMulticaster。

4. ApplicationListener(监听者)

接收并处理事件,通过实现接口或注解定义。

角色

对应组件

责任

事件

ApplicationEvent

信息载体

发布者

ApplicationEventPublisher

触发事件

广播器

ApplicationEventMulticaster

调度分发

监听者

ApplicationListener

 / @EventListener

处理事件

基于 Spring Cloud Alibaba + Gateway + Nacos + RocketMQ + Vue & Element 实现的后台管理系统 + 用户小程序,支持 RBAC 动态权限、多租户、数据权限、工作流、三方登录、支付、短信、商城等功能

  • 项目地址:https://github.com/YunaiV/yudao-cloud

  • 视频教程:https://doc.iocoder.cn/video/

两种使用方式:接口实现 vs 注解

方式一:实现 ApplicationListener 接口(传统方式)

Step 1:定义事件对象

public class OrderCreatedEvent extends ApplicationEvent {
    privatefinal String orderId;
    privatefinal Long userId;
    privatefinal BigDecimal totalAmount;

    public OrderCreatedEvent(Object source, String orderId, Long userId, BigDecimal totalAmount) {
        super(source);
        this.orderId = orderId;
        this.userId = userId;
        this.totalAmount = totalAmount;
    }

    public String getOrderId() { return orderId; }
    public Long getUserId() { return userId; }
    public BigDecimal getTotalAmount() { return totalAmount; }
}

Step 2:发布事件

@Service
publicclass OrderService {
    privatefinal ApplicationEventPublisher eventPublisher;

    public OrderService(ApplicationEventPublisher eventPublisher) {
        this.eventPublisher = eventPublisher;
    }

    @Transactional
    public Order createOrder(CreateOrderRequest req) {
        Order order = buildOrder(req);
        orderDao.save(order);
        eventPublisher.publishEvent(
            new OrderCreatedEvent(this, order.getId(), order.getUserId(), order.getTotalAmount())
        );
        return order;
    }
}

Step 3:实现监听器

@Component
publicclass SmsNotifyListener implements ApplicationListener<OrderCreatedEvent> {
    @Override
    public void onApplicationEvent(OrderCreatedEvent event) {
        smsService.send(event.getUserId(), "订单 " + event.getOrderId() + " 已提交");
    }
}

@Component
publicclass PointsListener implements ApplicationListener<OrderCreatedEvent> {
    @Override
    public void onApplicationEvent(OrderCreatedEvent event) {
        pointService.addPoints(event.getUserId(), event.getTotalAmount());
    }
}

缺点:一个监听器只能监听一种事件类型 ,类里只能有一个处理方法。

方式二:@EventListener 注解(推荐)

Spring 4.2 引入,灵活度大幅提升,主流写法:

@Component
publicclass OrderEventHandler {

    @EventListener
    public void handleSms(OrderCreatedEvent event) {
        smsService.send(event.getUserId(), "订单已提交");
    }

    // 同时监听多种事件
    @EventListener(value = {OrderCreatedEvent.class, OrderPaidEvent.class})
    public void handleOrderStateChange(ApplicationEvent event) {
        auditService.log(event);
    }

    // 条件监听:只处理金额 > 1000 元的
    @EventListener(condition = "#event.totalAmount > 1000")
    public void handleHighValueOrder(OrderCreatedEvent event) {
        vipService.notifyHighValue(event.getOrderId());
    }

    // 返回新事件:自动广播下一个
    @EventListener
    public InventoryUpdateEvent handleOrder(OrderCreatedEvent event) {
        returnnew InventoryUpdateEvent(this, event.getOrderId());
    }
}

几个少被提及的功能:**condition** 支持 SpEL 过滤;返回值如果是事件对象会自动发布,适合事件链;@Order 控制执行顺序。

@EventListener
@Order(1)  // 先执行
@Async
public void riskCheck(OrderCreatedEvent event) { ... }

@EventListener
@Order(2)  // 后执行
@Async
public void sendSms(OrderCreatedEvent event) { ... }

Spring 内置事件

Spring 在容器生命周期关键节点也会发布事件:

Spring内置事件类型列表
Spring内置事件类型列表

事件

触发时机

常用场景

ContextRefreshedEvent

容器初始化或刷新完成

预热缓存、加载配置

ContextStartedEvent

调用 context.start()

启动定时任务

ContextStoppedEvent

调用 context.stop()

清理资源

ContextClosedEvent

容器关闭

优雅关机

RequestHandledEvent

HTTP 请求处理完毕

请求监控

最常用的是 ContextRefreshedEvent,预热缓存 的经典用法:

@Component
public class CachePreloadListener {
    @EventListener(ContextRefreshedEvent.class)
    public void preloadCache(ContextRefreshedEvent event) {
        // 父子容器场景会触发两次,需要防守
        if (event.getApplicationContext().getParent() != null) {
            return;
        }
        CompletableFuture.runAsync(() -> {
            provinceService.loadAll();
            hotProductService.preload();
            log.info("缓存预热完成");
        });
    }
}

Spring Boot 里有更好用的 ApplicationReadyEvent,只触发一次:

@EventListener(ApplicationReadyEvent.class)
public void onReady() {
    cacheService.initAll();
}

同步还是异步?

Spring 事件默认同步 ——publishEvent() 会阻塞,等所有监听器执行完才继续。好处是简单、对事务友好;坏处是监听器卡顿会拖慢发布者 。

开启异步

三步搞定:

第一步:开启异步支持

@SpringBootApplication
@EnableAsync
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

第二步:配置专用线程池 (强烈建议,否则会用 ForkJoinPool.commonPool)

@Configuration
public class AsyncConfig {
    @Bean("eventExecutor")
    public Executor eventTaskExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(4);
        executor.setMaxPoolSize(16);
        executor.setQueueCapacity(500);
        executor.setThreadNamePrefix("event-async-");
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        executor.initialize();
        return executor;
    }
}

第三步:给监听器加 @Async

@Async("eventExecutor")
@EventListener
public void handleSms(OrderCreatedEvent event) {
    smsService.send(event.getUserId(), "订单已提交");
}
两个必知的异步局限

1. 异常不传播 :异步监听器的异常在线程池线程中自行消化,发布者完全感知不到。必须在监听器内 try-catch。

2. 返回值发布失效 :加了 @Async 后,返回事件对象不会自动发布,需手动 publishEvent。

@Async("eventExecutor")
@EventListener
public void handleSms(OrderCreatedEvent event) {
    try {
        smsService.send(event.getUserId(), "订单已提交");
    } catch (Exception e) {
        log.error("短信发送失败,订单 ID: {}", event.getOrderId(), e);
        alarmService.notify("SMS_FAILED", e.getMessage());
    }
}

@TransactionalEventListener:事务提交后再执行

场景:用户修改订单后删缓存。如果用普通 @EventListener,缓存删了但事务可能回滚——缓存击穿 。

@TransactionalEventListener 解决这个问题:

@TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT)
public void cleanCache(OrderUpdatedEvent event) {
    redisTemplate.delete("order:" + event.getOrderId());
}

phase

触发时机

AFTER_COMMIT

(默认)

事务成功提交后

AFTER_ROLLBACK

事务回滚后

AFTER_COMPLETION

事务完成后(无论成败)

BEFORE_COMMIT

事务提交前

两个隐形陷阱 :

1. 没有事务时事件会被丢弃

// 没有 @Transactional 的方法发布事件
public void someMethod() {
    eventPublisher.publishEvent(new OrderUpdatedEvent(...));
    // @TransactionalEventListener 会直接丢弃!
}

加 fallbackExecution = true 解决:

@TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT, fallbackExecution = true)
public void cleanCache(OrderUpdatedEvent event) {
    redisTemplate.delete("order:" + event.getOrderId());
}

2. AFTER_COMMIT 阶段里起不了新事务

事务已提交,加了 @Transactional 默认也不会新开事务,必须指定 Propagation.REQUIRES_NEW。

源码解析:事件是怎么走到监听器的

注册阶段

容器 refresh() 过程中完成两件事:

初始化广播器 :

protected void initApplicationEventMulticaster() {
    ConfigurableListableBeanFactory beanFactory = getBeanFactory();
    if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {
        this.applicationEventMulticaster = beanFactory.getBean(...);
    } else {
        this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
    }
}

注册监听器 :先注册编程式添加的监听器,再从 BeanFactory 找所有 ApplicationListener 接口的 Bean。@EventListener 注解由 EventListenerMethodProcessor 处理——在所有单例 Bean 初始化完成后扫描带注解的方法,封装为 ApplicationListenerMethodAdapter 注册到广播器。

分发阶段
// SimpleApplicationEventMulticaster#multicastEvent()
public void multicastEvent(ApplicationEvent event, ResolvableType eventType) {
    ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
    Executor executor = getTaskExecutor();
    for (ApplicationListener<?> listener : getApplicationListeners(event, type)) {
        if (executor != null) {
            executor.execute(() -> invokeListener(listener, event));
        } else {
            invokeListener(listener, event);
        }
    }
}

getApplicationListeners() 内部有缓存,首次调用遍历所有监听器做类型匹配,之后走缓存。

完整调用链:

publishEvent()
  └─ multicastEvent()
      └─ getApplicationListeners()(带缓存的匹配)
      └─ invokeListener()
          └─ doInvokeListener()
              └─ listener.onApplicationEvent()  ← 你的业务代码

踩坑实录

坑 1:事件对象设计成可变的
@EventListener
public void handleA(OrderCreatedEvent event) {
    event.setStatus("PROCESSING");  // 修改了事件对象
}

@EventListener
public void handleB(OrderCreatedEvent event) {
    // handleA 已经改了 status,这里看到脏数据
    doSomething(event.getStatus());
}

多个监听器共享同一个事件对象。事件对象必须不可变 :属性加 final,不提供 setter。

坑 2:开了 @Async 却没开 @EnableAsync
@EventListener
@Async
public void asyncHandle(OrderCreatedEvent event) {
    // 看起来异步,实际同步执行,而且无任何报错
}

@Async 不生效的表现是性能没提升却找不到原因。**@EnableAsync 必须加在主类或配置类上。**

坑 3:事件循环调用
@EventListener
public void handleA(EventA event) {
    eventPublisher.publishEvent(new EventB());
}
@EventListener
public void handleB(EventB event) {
    eventPublisher.publishEvent(new EventA());  // 死循环!StackOverflowError
}

设计事件时要明确依赖关系,避免形成环。

坑 4:@TransactionalEventListener 无事务时默默丢事件

上面已经提到。没事务 + 没设 fallbackExecution = true = 事件被默默丢弃,调试时极难发现。

Spring Event vs MQ:怎么选?

Spring Event 与 MQ 对比选型决策树
Spring Event 与 MQ 对比选型决策树

对比维度

Spring Event

MQ(Kafka/RocketMQ)

适用场景

同 JVM 内模块解耦

跨服务通信

可靠性

进程崩溃就丢事件

持久化 + 重试

延迟

内存级,≈ 0

受网络影响

开发成本

零依赖,注解即用

需部署中间件

一致性

本地事务保障

需分布式事务

吞吐量

异步+批量 ~9w/s

受网络并发限制

简单说:单体应用 / 同 JVM 逻辑解耦 / 不要求消息持久化 → Spring Event ;微服务跨服务通信 / 高可靠消息传输 → MQ 。

生产级最佳实践

1. 事件对象保持轻量 :只传 ID,不传大对象。

public class OrderCreatedEvent extends ApplicationEvent {
    private final String orderId;
    private final String version = "1.0";
}

2. 一个监听器只做一件事 :PaymentListener 只处理支付,CouponListener 只发券。

3. 异步监听器必须自己捕异常 。

4. 加监控 :关键链路的监听器加耗时统计和告警。

5. 事件命名要语义化 :用过去式动词——OrderCreatedEvent、PaymentSuccessEvent。不要用 DoSomethingEvent。

回到开头那个问题

那个越写越胖的 createOrder,用事件机制改造:

@Transactional
public Order createOrder(CreateOrderRequest req) {
    Order order = buildOrder(req);
    orderDao.save(order);
    eventPublisher.publishEvent(new OrderCreatedEvent(this, order));
    return order;
}

// 新增功能?加个监听器就好,不动核心代码
@Component
publicclass NewFeatureListener {
    @EventListener
    public void handleNewFeature(OrderCreatedEvent event) {
        // 新功能在这里
    }
}

一个经得起考验的系统,不是靠把所有逻辑塞进一个方法里,而是让不同模块各司其职。Spring 事件机制,正是实现这种协作的工具。


欢迎加入我的知识星球,全面提升技术能力。

👉 加入方式,“长按”或“扫描”下方二维码噢:

星球的内容包括:项目实战、面试招聘、源码解析、学习路线。

文章有帮助的话,在看,转发吧。
谢谢支持哟 (*^__^*)
Android BluetoothSocket BluetoothSocket是Android中用于在蓝牙设备之间进行数据传输的一种Socket。它提供了一种类似于TCP/IP协议的数据传输方式,可以在两个设备之间建立一个虚拟的通信管道,使得两个设备之间可以进行数据的传输和接收。BluetoothSocket可以用于客户端和服务端之间的通信,通过BluetoothSocket可以实现数据的双向传输。 阅读详情

相关推荐

LightTools 中LCD投影仿真的checkerboard pattern偏振控制技术解析

本文深入解析了在LightTools软件中进行LCD投影仿真时,利用checkerboard pattern(棋盘格图案)结合偏振控制技术来模拟液晶面板像素开关、提升图像对比度的核心方法。文章从实战角度出发,详细拆解了通过设置波片(如1/2波片)和偏振片来操控S光与P光转换的原理,并分享了在LightTools中搭建仿真模型、使用VBA脚本自动化配置参数以提高效率的实用技巧,为光学工程师优化投影系统仿真流程提供了清晰指导。

weixin_29305313的博客 345

Spring AI 流程编排:AI时代,你需要一个更轻量的 Spring 流程编排框架

本文论述AI时代轻量级Spring流程编排框架的必要性。随着AI应用从简单模型调用发展为复杂流程系统,传统重量级工作流平台过于笨重,而Salt Function Flow等轻量框架能以Java原生DSL嵌入Spring Boot,通过next、concurrent、loop等API统一编排Prompt、LLM、Agent、RAG等节点,实现AI与业务逻辑的同构执行,让流程结构显式可见、执行控制与业务分离,填补"需要编排但无需BPMN平台"的中间场景。

花千树的专栏 827

从零到实战:用QCustomPlot在QT中绘制动态曲线图(含OpenGL加速配置)

本文详细介绍了如何在QT中使用QCustomPlot库绘制动态曲线图,并配置OpenGL加速以提升渲染性能。从环境搭建、动态数据可视化到OpenGL加速配置,手把手教你实现工业级动态曲线监控系统,适用于大数据量实时展示场景。

weixin_29019241的博客 354

Mockito verify() 深度解析:行为验证原理与生产级实践

在 Java 单元测试中,verify() 并非简单断言工具,而是对对象间协作行为的契约化验证机制。其底层依赖调用记录器(Invocation Tracker)实现‘事后回放’式分析,通过 VerificationMode(如 times、never、timeout)将业务规则映射为可执行的验证策略。相比 assert 关注状态输出,verify() 聚焦过程协作,天然支持外部依赖隔离,是构建高可信度测试的核心能力。结合参数匹配(eq/refEq/argThat)、ArgumentCaptor 取证、inO

weixin_30727835的博客 419

CXL3.0 CDAT(Coherent Device Attributes Table)

在说明CDAT之前,先讲一下CXL中的DOE类型:CXL协议里定义了两种DOE的类型,一种是Compliance就是合规性测试的内容,还有一种就是CDAT(一致性属性表)Memory_Info_Valid是CXL设备的内存配置完成标志,位于DVSEC(Designated Vendor-Specific Extended Capability)的CXL Range X Size Low寄存器中(X为1或2)。

Summer的博客 1438

Windows11配置WSL2支持代理上网

说起来本来这个功能我也不需要的,只是最近突然有个需求就顺便研究了下,WSL2默认的网络方式是NAT,即WSL2的网卡本身是虚拟网卡,通过以太网或WIFI的地址转换来上互联网,我试了下是不能直接走代理的,最近比较忙没具体研究,但是我用另一种方式实现了,下面介绍给需要的人。注意:这个方法只能是WIndows11系统,WIndows10系统上的WSL2缺少了一项功能导致不可用。1、方法总体没什么难度,NAT方式暂时没研究透,后续有时间再研究2、WIndows10系统不支持mirrored,暂时需要另辟蹊径。

jiexijihe945的博客 9592

Golang基础面试题汇总

channel、goroutine、slice、map、反射、内存、GC、Musql、Redis、ELK、K8s、Http、Https

weixin_41760738的博客 5697

YOLOv11与Roboflow数据预处理实战:从原始数据到高性能模型

摘要 Roboflow平台与YOLOv11的结合为计算机视觉开发者提供了高效的工作流。Roboflow提供数据集管理、预处理、增强和导出的一站式解决方案,支持多种标注格式并与YOLOv11无缝集成。YOLOv11在YOLO系列基础上进行了架构创新,包括深度宽度优化、C3k2机制和C2PSA注意力机制,提供从纳米版到超大版的多种模型变体。 使用Roboflow的流程包括:注册工作区、收集/导入数据(支持本地和公开数据集)、专业标注(含SAM辅助)、预处理(尺寸调整、归一化等)和数据增强(几何变换和颜色调整)。

本博客聚焦 YOLOv11 全流程落地,涵盖架构优化、数据集处理、训练技巧与多场景部署,兼及国产数据库、Java 开发与 AI 模型应用,内容兼顾理论与工程实践,为开发者提供系统干货,助力高效提升技术能力。 353

压缩省了60%磁盘,写入TPS掉了25%——InnoDB页压缩的三类隐性代价与适用边界

InnoDB页压缩能显著降低表空间占用,但磁盘的节省不是免费的。压缩页在写入时需要CPU执行压缩算法、读取时需要CPU解压;压缩后的页在Buffer Pool中占用更少空间,但命中后的解压开销和未命中时的解压延迟会改变缓存的实际效能;写密集场景下,压缩/解压带来的写入放大可能让TPS明显下降。本文拆解InnoDB页压缩的物理机制、三类隐性代价的量化表现,以及“什么场景该用、什么场景该绕开”的判断框架。

DBAxiaoye的博客 332

数字人接大模型第二步:语音克隆

推荐XTTS-v2项目,由Coqui公司开发的语音生成模型,专为多语言语音克隆和生成设计。它支持17种语言,包括英语、西班牙语、法语、德语、意大利语、葡萄牙语、波兰语、土耳其语、俄罗斯语、荷兰语、捷克语、阿拉伯语、中文、日语、匈牙利语、韩语和印地语。XTTS-v2的核心优势在于其仅需6秒的音频片段即可实现语音克隆,无需大量的训练数据。此外,它还支持情感和风格转移、跨语言语音克隆以及多语言语音生成,采样率高达24kHz。地址:https://github.com/archwesome/XTTS-v2。

404

Spring AI 实战:第五章、Spring AI本地模型部署之省钱小能手

白嫖的快乐你想象不到经过这番折腾,我们成功实现了零成本使用大模型完全本地运行保障隐私可视化访问Java生态无缝集成但可能有的小伙伴要吐槽,怎么换个底层模型这次就新建一个工程了呢?不能在以前的工程上开发吗?这样也太不优雅了吧~,我知道你很急,但先别急,等下一章节再来解决这个问题。为什么程序员特别喜欢Ollama?因为它就像一只温顺的羊驼——不花钱还能24小时产出代码!

liaokailin的专栏 922

实际工程问题:AI 生成 Spring Cache(@Cacheable / @CachePut / @CacheEvict)缓存注解踩坑

商品详情服务,要求:商品基础信息走缓存,减少 DB 查询;典型:AI 只贴注解,忽略 AOP 代理、key 设计、缓存穿透/击穿/过期、序列化、同步刷新,本地单测正常,上线后缓存脏数据、命中率异常、雪崩。如果业务在事务中,@CacheEvict / @CachePut 如果在事务提交前执行,一旦事务回滚,缓存已经被删掉/更新,数据不一致。• 如果在同一个类里用 this.xxx() 调用带缓存注解的方法,不走代理,缓存直接失效;// 更新商品:先更新 DB,再删除缓存,而不是直接 @CachePut。

2401_89363342的博客 489

基于STM32的录音机设计(STM32F103+VS1053B)

本项目设计并实现了一款基于STM32微控制器的便携式录音机。该录音机采用STM32F103C8T6作为主控芯片,结合VS1053B音频编解码模块、SD卡存储、OLED显示屏以及按键模块,提供了手动录音、自动录音和录音回放等多种功能。

1万+

第三篇 第 6 课

前置:第三篇第 1 课(stdx 引入),第二篇第 1 课(std.regex)。环境:仓颉 SDK 1.2.0。本文所有代码与输出均逐行实测。

weixin_41618057的博客 527

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

V8 机制、手写核心函数与 TypeScript 类型体操

或固定初始化(如数组先定长、对象先给全字段)保持类型与形状稳定;这些都比"换框架"更基础。只能处理纯数据(丢函数、Date、RegExp、循环引用报错)。生产级深拷贝要处理:原始值短路、循环引用、V8(Chrome / Node 的 JS 引擎)不是"解释一行跑一行"那么简单,它用。图:V8 执行流程——解释执行 + 热点优化,优化失败会 Deopt 回退。JS 内存自动管理,但"自动"不等于"不会漏"。是"固定间隔最多执行一次"。手写 Promise 是"懂异步"的试金石。是"停下后才执行最后一次",

qq_38468358的博客 355

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

MCP 2026-07-28 无状态协议大改版:Spring AI 2.1 多轮往返请求与网关路由落地

无状态,所以任何实例都能处理任何请求,扩容不再需要粘性会话;显式句柄,所以跨调用状态是可审计、可过期的,而不是藏在进程内存里;幂等重放,所以交互式中断在分布式环境下也可恢复,代价是你要自己保证副作用可对账;头部路由,所以网关能在不解析 body 的前提下做治理,而校验 header/body 一致性成了新的安全底线。这些没有一个是在发明新概念。它们是分布式系统里被验证过二十年的老手艺:无状态、显式上下文、幂等、网关治理、fail-fast、可观测。

qq_36021478的博客 168

模型“看不见”中间的东西——prompt cache 与 Zone 分区

本文揭示了LLM系统中promptcache失效的根源:动态内容错置于系统提示词前缀,导致缓存命中率从80%骤降至4%。核心教训是“变化内容必须排在最后”——通过Zone分区(ZoneA稳定区、ZoneB动态区),将每轮可能变化的内容移至末尾,可确保前缀稳定,恢复高命中率。关键在于:前缀匹配要求逐字节相同,任何一处变动即导致后续全部失效。修复建议包括:重构提示词结构、正确分类内容、监控缓存单位(字节与token不可混用)、避免压缩破坏前缀。最终实现成本降低9倍,提升推理效率。

qinglongcn的博客 220

SpringBoot 新闻推荐系统:88个Java文件105个接口,首页推荐位是后端按点击数排出来的

# SpringBoot 新闻推荐系统:88个Java文件105个接口,首页推荐位是后端按点击数排出来的 > 这是一套基于 Spring Boot 的新闻推荐系统源码,配套 `db.sql` 建表脚本,业务覆盖新闻发布、排行榜管理、评论回复、点赞点踩、收藏夹和轮播图配置。形态是**前后台双端**:前台是读者用的 layui 静态站,后台是管理员用的 Vue 单页应用(编译产物已嵌在工程里)。最值

面朝大海 875

Spring 事务详解:@Transactional 如何生效、何时回滚、传播行为怎么选

从订单与库存写入出发,拆解 @Transactional 的代理调用链、默认回滚规则与自调用问题;通过 Spring Boot + H2 的五个验证用例比较 REQUIRED、REQUIRES_NEW、NESTED,并说明数据库事务与 Redis、消息和远程接口的边界。

qq_74421990的博客 332

【从零理解 Spring AI · 12】MCP 的两种角色:做客户端还是做服务端

上一篇讲了 MCP 的概念:标准协议、三大角色、M+N 替代 M×N。

nice_lcj520的博客 564

Spring Framework 7 HTTP Interface 实战:声明式 RestClient、超时与测试

Spring Framework 7 中,Java 开发者如何使用 HTTP Interface 管理外部服务调用?本文从传统 RestClient 出发,介绍 @HttpExchange、`@GetExchange`、`RestClientAdapter` 和 HttpServiceProxyFactory 的使用方式,并结合商品服务案例说明客户端配置、超时控制、异常处理及 Mock 测试。最后讨论从 RestTemplate、Feign 迁移时的技术取舍,帮助开发者建立更清晰的 HTTP 客户端架构。

代码不止,探索不息 254

基于 Springboot3+SpringAI+Agent+RAG+Function Calling的校园闲置物品循环流转 AI 智能估价平台

基于SpringBoot3+SpringAI1.0,打造校园闲置循环平台,实现从发布、智能估价(规则+大模型校准)、担保交易到信用治理与运营看板的闭环。通过RAG问答、FunctionCalling工具调用、流式SSE输出及本地降级策略,将AI能力深度嵌入业务链路。项目强调可落地性:无APIKey也能演示,向量存MySQL,状态机防绕过,代码清晰可读。适合想做真实AI全栈项目、准备面试或提升工程化思维的开发者。

深耕开发,专注编程实战。分享源码解析、项目搭建、问题排查笔记,沉淀技术,持续更新。 311

SpringBoot「衣依」服装销售平台:144个Java文件180个接口,从挑衣服到收货评价整条链路都在

# SpringBoot「衣依」服装销售平台:144个Java文件180个接口,从挑衣服到收货评价整条链路都在 > 这是一套基于 Spring Boot 的服装销售平台源码,配套 `db.sql` 建表脚本,业务覆盖商品展示、购物车、订单流转、收货地址、订单评价、商品评论、在线客服、轮播图和资讯。形态是**前后台双端**:前台是顾客逛的商城,后台是管理员管的控制台。本文带你看清里面有什么、怎么跑

面朝大海 229

Spring AI开发从入门到实践-什么是Spring AI

《Spring AI开发从入门到实践》是面向Java开发者的企业级AI应用指南,基于Spring生态构建,实现LLM、向量库、智能体等技术的低门槛集成。书中以“不造模型,只做连接”为核心,通过统一API屏蔽厂商差异,原生支持自动配置、可观测性等工程能力,解决AI从Demo到生产落地的痛点。全书分五部分,覆盖环境搭建、核心组件、实战应用、生产优化与前沿探索,配套可运行代码,助力开发者无缝将AI融入现有系统,真正实现企业级落地。

老卫的技术站 142

基于SpringBoot的营养食谱管理系统设计与实现-附源码

基于SpringBoot的营养食谱管理系统,实现食谱、食材与营养数据的数字化管理,支持多条件筛选、个性化饮食方案定制及收藏功能,助力用户科学饮食,提升营养师管理效率。系统采用前后端分离架构,技术栈成熟,功能完整,测试验证通过,具备良好可扩展性,未来可集成体质测评、饮食打卡等智能功能。

专注于大学生项目实战开发,讲解,毕业答疑辅导,java就业辅导,高校老师/讲师/同行合作。以及产品测评宣传、工具推广等合作。全网粉丝10w+,平台优质java、小程序创作者。 326

《Springboot3-AOT》

AOT:提前编译 程序执行前,全部被编译成机器码JIT:即时编译 程序边编译边运行编译:源代码 ====== 机器码 机器才能执行。

shuoshuohaohao的博客 216

JavaWeb-day13-SpringBootWeb事务管理&AOP

本文介绍了Spring事务管理和AOP编程的实际应用。在事务管理部分,通过部门删除案例展示了@Transactional注解的使用,包括事务回滚和传播行为设置,演示了如何保证数据一致性。AOP部分详细讲解了切面编程的核心概念,包括通知类型、切入点表达式和连接点操作,并通过日志记录案例展示了如何利用AOP实现统一的操作日志记录功能。文中提供了完整的代码示例,涵盖事务管理、日志注解定义、切面类实现以及相关Mapper和Service层代码,体现了Spring框架在企业级应用开发中的强大功能。

chasing_dreamsss的博客 90
上一篇: Star 13.3k 内网穿透工具 Rust 语言编写 frp,ngrok 替代
下一篇: 最近AI圈爆火的Hermes到底是什么?
公众号-芋道源码
博客等级 码龄10年 1634粉丝 377原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值