Spring Boot事件机制详解

news2025/3/26 3:56:48

Spring Boot事件机制详解

1. 事件机制基础

1.1 什么是事件驱动架构

事件驱动架构(Event-Driven Architecture, EDA)是一种软件设计模式,其中系统组件通过事件的发布与订阅进行通信。在Spring Boot中,事件机制为应用程序提供了松耦合的组件间通信方式,使得发布者无需关心谁在监听,监听者也无需了解事件来源。

这种设计类似于现实生活中的"广播通知":

  • 广播站(事件发布者)发布新闻
  • 听众(事件监听者)根据自己的兴趣选择接收信息
  • 广播站与听众之间不存在直接依赖关系

1.2 Spring事件机制核心组件

组件描述主要职责
事件(Event)封装状态变化的消息载体定义事件属性、携带上下文信息
发布者(Publisher)事件的触发方创建事件对象并发布到事件总线
监听者(Listener)事件的处理方注册感兴趣的事件并实现处理逻辑
事件总线(Event Bus)事件传播的通道管理事件的分发与监听者调用

1.3 Spring内置事件概览

Spring框架自身定义了多种内置事件,用于标识应用生命周期中的关键节点:

  • ContextRefreshedEvent: 当ApplicationContext初始化或刷新完成时触发
  • ContextStartedEvent: 当ApplicationContext启动时触发(显式调用start()方法)
  • ContextStoppedEvent: 当ApplicationContext停止时触发(显式调用stop()方法)
  • ContextClosedEvent: 当ApplicationContext关闭时触发
  • RequestHandledEvent: 在Web应用中,当HTTP请求处理完成时触发

Spring Boot在此基础上扩展了更多事件:

  • ApplicationStartingEvent: 应用启动开始,除注册监听器和初始化器外,未进行任何处理
  • ApplicationEnvironmentPreparedEvent: 环境准备完成,但上下文创建之前
  • ApplicationContextInitializedEvent: 上下文已创建并准备就绪,但源未加载
  • ApplicationPreparedEvent: 配置和Bean定义加载完成,但上下文未刷新
  • ApplicationStartedEvent: 上下文刷新完成,应用启动但未接收命令行或Web请求
  • ApplicationReadyEvent: 应用已准备就绪,可以接收请求
  • ApplicationFailedEvent: 启动异常时触发

2. 自定义事件实现

2.1 基础实现方式

2.1.1 定义事件
// 方式一:继承ApplicationEvent(传统方式)
public class UserCreatedEvent extends ApplicationEvent {
    private final String username;
    
    public UserCreatedEvent(Object source, String username) {
        super(source);
        this.username = username;
    }
    
    public String getUsername() {
        return username;
    }
}

// 方式二:POJO事件(Spring 4.2+推荐方式)
public class ProductCreatedEvent {
    private final String productId;
    private final LocalDateTime createdTime;
    
    public ProductCreatedEvent(String productId) {
        this.productId = productId;
        this.createdTime = LocalDateTime.now();
    }
    
    // getter方法
}
2.1.2 创建监听器
// 方式一:实现ApplicationListener接口
@Component
public class UserEventListener implements ApplicationListener<UserCreatedEvent> {
    private static final Logger logger = LoggerFactory.getLogger(UserEventListener.class);
    
    @Override
    public void onApplicationEvent(UserCreatedEvent event) {
        logger.info("用户创建事件被监听到,用户名: {}", event.getUsername());
        // 执行业务逻辑
    }
}

// 方式二:使用@EventListener注解(Spring 4.2+推荐方式)
@Component
public class ProductEventListener {
    private static final Logger logger = LoggerFactory.getLogger(ProductEventListener.class);
    
    @EventListener
    public void handleProductCreated(ProductCreatedEvent event) {
        logger.info("产品创建事件被监听到,产品ID: {}", event.getProductId());
        // 执行业务逻辑
    }
}
2.1.3 发布事件
@Service
public class UserService {
    private final ApplicationEventPublisher eventPublisher;
    
    // 通过构造函数注入ApplicationEventPublisher
    public UserService(ApplicationEventPublisher eventPublisher) {
        this.eventPublisher = eventPublisher;
    }
    
    public void createUser(String username) {
        // 业务逻辑
        logger.info("创建用户: {}", username);
        
        // 发布事件
        eventPublisher.publishEvent(new UserCreatedEvent(this, username));
    }
}

@Service
public class ProductService {
    private final ApplicationEventPublisher eventPublisher;
    
    public ProductService(ApplicationEventPublisher eventPublisher) {
        this.eventPublisher = eventPublisher;
    }
    
    public void createProduct(String productId) {
        // 业务逻辑
        logger.info("创建产品: {}", productId);
        
        // 发布POJO事件
        eventPublisher.publishEvent(new ProductCreatedEvent(productId));
    }
}

2.2 高级特性

2.2.1 条件事件监听

Spring允许在事件监听器上添加条件,仅当条件满足时才触发监听器:

@Component
public class ConditionalEventListener {
    
    @EventListener(condition = "#event.productId.startsWith('PREMIUM')")
    public void handlePremiumProductOnly(ProductCreatedEvent event) {
        // 仅处理高级产品
    }
    
    @EventListener(condition = "#{systemProperties['env'] == 'PRODUCTION'}")
    public void handleInProductionOnly(UserCreatedEvent event) {
        // 仅在生产环境处理
    }
}
2.2.2 事件监听顺序控制

当多个监听器订阅同一事件时,可使用@Order注解控制执行顺序:

@Component
public class OrderedEventListeners {
    
    @EventListener
    @Order(1) // 最高优先级
    public void handleWithHighestPriority(UserCreatedEvent event) {
        // 先执行此方法
    }
    
    @EventListener
    @Order(5) // 中等优先级
    public void handleWithMediumPriority(UserCreatedEvent event) {
        // 然后执行此方法
    }
    
    @EventListener
    @Order(10) // 最低优先级
    public void handleWithLowestPriority(UserCreatedEvent event) {
        // 最后执行此方法
    }
}
2.2.3 事件监听返回值作为新事件

事件监听方法可以返回一个对象,此对象将被自动发布为新的事件:

@Component
public class TransactionalEventListener {
    
    @EventListener
    public NotificationEvent handleUserCreated(UserCreatedEvent event) {
        // 处理用户创建事件
        
        // 返回通知事件,将被自动发布
        return new NotificationEvent("用户 " + event.getUsername() + " 已创建");
    }
    
    @EventListener
    public List<NotificationEvent> handleProductCreated(ProductCreatedEvent event) {
        // 可以返回多个事件
        return Arrays.asList(
            new NotificationEvent("产品已创建"),
            new LoggingEvent("产品创建日志记录")
        );
    }
}

3. 异步事件处理

3.1 启用异步事件支持

默认情况下,Spring事件处理是同步的,发布者线程会等待所有监听者执行完毕才返回。开启异步支持:

@Configuration
@EnableAsync
public class AsyncConfig implements AsyncConfigurer {
    
    @Override
    public Executor getAsyncExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(5);
        executor.setMaxPoolSize(10);
        executor.setQueueCapacity(25);
        executor.setThreadNamePrefix("event-async-");
        executor.initialize();
        return executor;
    }
    
    @Override
    public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
        return new SimpleAsyncUncaughtExceptionHandler();
    }
}

3.2 异步事件监听器

@Component
public class AsyncEventListener {
    
    @Async
    @EventListener
    public void handleAsynchronously(UserCreatedEvent event) {
        // 此方法将在单独的线程中执行
        logger.info("异步处理用户创建事件,线程: {}", Thread.currentThread().getName());
    }
}

3.3 同步与异步对比

特性同步事件异步事件
执行线程发布者线程线程池中的线程
执行顺序可预测的顺序不确定的顺序
事务传播共享发布者事务独立事务上下文
异常处理异常会传播到发布者异常在线程池中处理
适用场景关键业务流程非关键后台处理

4. 事务事件处理

4.1 事务绑定事件

Spring提供了@TransactionalEventListener注解,允许将事件处理与事务状态绑定:

@Component
public class OrderTransactionalEventListener {
    
    @TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT)
    public void handleAfterCommit(OrderCreatedEvent event) {
        // 仅在事务成功提交后执行
        // 适合发送通知、更新缓存等操作
    }
    
    @TransactionalEventListener(phase = TransactionPhase.AFTER_ROLLBACK)
    public void handleAfterRollback(OrderCreatedEvent event) {
        // 仅在事务回滚后执行
        // 适合记录失败信息、发送告警等
    }
    
    @TransactionalEventListener(phase = TransactionPhase.AFTER_COMPLETION)
    public void handleAfterCompletion(OrderCreatedEvent event) {
        // 在事务完成后执行(无论提交或回滚)
        // 适合清理资源等操作
    }
    
    @TransactionalEventListener(phase = TransactionPhase.BEFORE_COMMIT)
    public void handleBeforeCommit(OrderCreatedEvent event) {
        // 在事务提交前执行
        // 适合最终验证等操作
    }
}

4.2 事务事件处理失败策略

@TransactionalEventListener提供了fallbackExecution属性,控制无事务环境下的行为:

@Component
public class FallbackEventListener {
    
    @TransactionalEventListener(
        phase = TransactionPhase.AFTER_COMMIT,
        fallbackExecution = true  // 即使没有事务也会执行
    )
    public void handleWithFallback(OrderCreatedEvent event) {
        // 在事务提交后执行,或在没有事务的情况下也执行
    }
    
    @TransactionalEventListener(
        phase = TransactionPhase.AFTER_COMMIT,
        fallbackExecution = false  // 默认值,没有事务则不执行
    )
    public void handleWithoutFallback(OrderCreatedEvent event) {
        // 仅在事务提交后执行,没有事务则不执行
    }
}

5. 实战应用场景

5.1 系统通知场景

// 事件定义
public class SystemNotificationEvent {
    private final String title;
    private final String content;
    private final NotificationLevel level;
    
    // 构造函数和getter方法
    
    public enum NotificationLevel {
        INFO, WARNING, ERROR, CRITICAL
    }
}

// 多渠道通知监听器
@Component
public class NotificationListeners {
    
    @EventListener
    @Order(1)
    public void logNotification(SystemNotificationEvent event) {
        // 记录所有通知
        String logLevel = switch(event.getLevel()) {
            case INFO -> "INFO";
            case WARNING -> "WARN";
            case ERROR, CRITICAL -> "ERROR";
        };
        logger.atLevel(Level.valueOf(logLevel))
              .log("系统通知: {} - {}", event.getTitle(), event.getContent());
    }
    
    @EventListener(condition = "#event.level == T(com.example.SystemNotificationEvent.NotificationLevel).WARNING " +
                           "or #event.level.name() == 'ERROR'")
    @Order(2)
    public void emailNotification(SystemNotificationEvent event) {
        // 发送邮件通知
        emailService.sendEmail(
            "系统通知: " + event.getTitle(),
            event.getContent()
        );
    }
    
    @Async
    @EventListener(condition = "#event.level.name() == 'CRITICAL'")
    @Order(3)
    public void smsNotification(SystemNotificationEvent event) {
        // 发送短信通知
        smsService.sendSms(
            "紧急系统通知: " + event.getTitle(),
            event.getContent()
        );
    }
}

5.2 缓存更新场景

// 事件定义
public class EntityChangedEvent<T> {
    private final T entity;
    private final ChangeType changeType;
    private final Class<T> entityType;
    
    // 构造函数和getter方法
    
    public enum ChangeType {
        CREATED, UPDATED, DELETED
    }
}

// 缓存更新监听器
@Component
public class CacheUpdateListener {
    
    private final CacheManager cacheManager;
    
    public CacheUpdateListener(CacheManager cacheManager) {
        this.cacheManager = cacheManager;
    }
    
    @TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT)
    public void handleProductChange(EntityChangedEvent<Product> event) {
        String cacheKey = "product:" + event.getEntity().getId();
        Cache productCache = cacheManager.getCache("products");
        
        switch(event.getChangeType()) {
            case CREATED, UPDATED:
                productCache.put(cacheKey, event.getEntity());
                break;
            case DELETED:
                productCache.evict(cacheKey);
                break;
        }
    }
}

// 在服务中发布事件
@Service
@Transactional
public class ProductService {
    
    private final ApplicationEventPublisher eventPublisher;
    
    // 构造函数
    
    public Product updateProduct(Product product) {
        // 业务逻辑
        Product updated = productRepository.save(product);
        
        // 发布事件
        eventPublisher.publishEvent(
            new EntityChangedEvent<>(updated, EntityChangedEvent.ChangeType.UPDATED, Product.class)
        );
        
        return updated;
    }
}

5.3 审计日志场景

// 定义审计事件
public class AuditEvent {
    private final String principal;
    private final String action;
    private final String resource;
    private final Map<String, Object> details;
    private final LocalDateTime timestamp;
    
    // 构造函数和getter方法
}

// 审计监听器
@Component
public class AuditEventListener {
    
    private final AuditRepository auditRepository;
    
    // 构造函数
    
    @Async
    @EventListener
    public void persistAuditLog(AuditEvent event) {
        AuditLog log = new AuditLog();
        log.setPrincipal(event.getPrincipal());
        log.setAction(event.getAction());
        log.setResource(event.getResource());
        log.setDetails(objectMapper.writeValueAsString(event.getDetails()));
        log.setTimestamp(event.getTimestamp());
        
        auditRepository.save(log);
    }
}

// 在控制器中使用
@RestController
@RequestMapping("/api/users")
public class UserController {
    
    private final UserService userService;
    private final ApplicationEventPublisher eventPublisher;
    
    // 构造函数
    
    @PostMapping
    public ResponseEntity<User> createUser(@RequestBody User user, Principal principal) {
        User created = userService.createUser(user);
        
        // 发布审计事件
        eventPublisher.publishEvent(new AuditEvent(
            principal.getName(),
            "CREATE",
            "USER:" + created.getId(),
            Map.of("username", created.getUsername(), "email", created.getEmail()),
            LocalDateTime.now()
        ));
        
        return ResponseEntity.created(URI.create("/api/users/" + created.getId()))
                           .body(created);
    }
}

6. 最佳实践与优化建议

6.1 设计原则

  1. 事件粒度控制

    • 事件应该表示"已发生的事实",使用过去时态命名
    • 避免过细粒度导致事件爆炸,也避免过粗粒度导致语义不清
  2. 事件数据包含

    • 包含足够上下文信息,但避免过度包含导致内存压力
    • 考虑仅包含ID等引用信息,而非完整对象图
  3. 监听器职责单一

    • 每个监听器专注处理特定类型的业务逻辑
    • 避免在单个监听器中耦合多种不相关的处理逻辑

6.2 性能优化

  1. 异步处理大批量事件

    • 对非关键路径使用@Async提高吞吐量
    • 为异步事件处理配置专用线程池,避免阻塞其他异步操作
  2. 避免监听器中的阻塞操作

    • 监听器中避免进行远程调用、复杂计算等阻塞操作
    • 考虑在监听器中进一步委派任务到专用工作线程
  3. 批量事件处理

    • 对高频事件,考虑批量收集后一次性处理
    • 使用定时任务或缓冲区策略减少处理次数

6.3 异常处理策略

  1. 同步监听器异常处理

    • 同步监听器中的异常会传播到发布者
    • 关键业务流程应在监听器中妥善捕获异常,避免影响主流程
  2. 异步监听器异常处理

    • 配置全局AsyncUncaughtExceptionHandler处理未捕获异常
    • 在监听器内部使用try-catch块并记录详细日志
  3. 事务监听器异常处理

    • @TransactionalEventListener的异常不会回滚主事务
      • phase = BEFORE_COMMIT除外
    • 对关键操作,考虑使用补偿机制或重试策略

6.4 测试策略

  1. 事件发布测试

    • 使用ApplicationEventPublisherAware接口验证事件发布
    • 使用ArgumentCaptor捕获并验证事件内容
  2. 监听器测试

    • 直接调用监听方法进行单元测试
    • 使用Spring Test提供的测试事件发布机制
  3. 端到端测试

    • 使用@SpringBootTest进行完整集成测试
    • 验证事件监听带来的系统状态变化

7. Spring Boot 3.x新特性

7.1 函数式风格事件监听

Spring Boot 3.x增强了对函数式编程风格的支持:

@Configuration
public class FunctionalEventConfig {
    
    @Bean
    public ApplicationListener<ProductCreatedEvent> productCreatedListener() {
        return event -> {
            // 函数式处理逻辑
            logger.info("函数式监听器: 产品已创建 - {}", event.getProductId());
        };
    }
    
    @Bean
    public ApplicationListener<ApplicationReadyEvent> applicationReadyListener() {
        return event -> {
            // 应用就绪后的处理逻辑
        };
    }
}

7.2 泛型事件处理

Spring Boot 3.x改进了对泛型事件的支持:

// 泛型基础事件
public class EntityEvent<T> {
    private final T entity;
    private final String action;
    
    // 构造函数和getter
}

// 泛型监听器
@Component
public class GenericEntityListener {
    
    @EventListener
    public void handleUserEvent(EntityEvent<User> event) {
        // 专门处理User实体事件
    }
    
    @EventListener
    public void handleProductEvent(EntityEvent<Product> event) {
        // 专门处理Product实体事件
    }
    
    @EventListener
    public void handleAnyEntityEvent(EntityEvent<?> event) {
        // 处理任何实体事件
    }
}

7.3 响应式事件支持

Spring Boot 3.x进一步增强了与Project Reactor的集成:

// 响应式事件发布
@Service
public class ReactiveProductService {
    
    private final ApplicationEventPublisher eventPublisher;
    
    // 构造函数
    
    public Mono<Product> createProduct(Product product) {
        return productRepository.save(product)
            .doOnSuccess(saved -> {
                // 发布事件
                eventPublisher.publishEvent(new ProductCreatedEvent(saved.getId()));
            });
    }
}

// 与响应式流结合的监听器
@Component
public class ReactiveEventListener {
    
    private final ProductSearchRepository searchRepository;
    
    // 构造函数
    
    @EventListener
    public void updateSearchIndex(ProductCreatedEvent event) {
        // 使用响应式API更新搜索索引
        searchRepository.findById(event.getProductId())
            .flatMap(product -> searchRepository.index(product))
            .subscribe(
                indexed -> logger.info("产品已索引: {}", event.getProductId()),
                error -> logger.error("索引失败: {}", error.getMessage())
            );
    }
}

8. 排错指南

8.1 常见问题与解决方案

问题可能原因解决方案
事件监听器未被调用1. 监听器未注册为Spring Bean
2. 事件类型不匹配
1. 确保使用@Component注解
2. 检查事件类型继承关系
事务事件监听器未执行1. 没有活跃事务
2. 事务传播行为不正确
1. 检查@Transactional注解位置
2. 考虑设置fallbackExecution=true
异步事件死锁1. 线程池配置不当
2. 事件监听链过长
1. 增加线程池容量
2. 拆分事件处理链路
事件处理顺序错乱未正确设置@Order注解为监听方法添加明确的@Order值
内存压力过大1. 事件对象过大
2. 事件发布频率过高
1. 减少事件中的数据量
2. 实现批处理机制

8.2 调试技巧

  1. 启用Spring事件DEBUG日志

    logging.level.org.springframework.context.event=DEBUG
    
  2. 监控事件发布情况

    @Aspect
    @Component
    public class EventPublishingAspect {
        
        @Around("execution(* org.springframework.context.ApplicationEventPublisher.publishEvent(..))")
        public Object logEventPublishing(ProceedingJoinPoint pjp) throws Throwable {
            Object event = pjp.getArgs()[0];
            logger.debug("发布事件: {}", event);
            long start = System.currentTimeMillis();
            try {
                return pjp.proceed();
            } finally {
                logger.debug("事件处理完成: {}, 耗时: {}ms", 
                           event, System.currentTimeMillis() - start);
            }
        }
    }
    
  3. 监控监听器执行情况

    @Aspect
    @Component
    public class EventListenerAspect {
        
        @Around("@annotation(org.springframework.context.event.EventListener)")
        public Object logEventListener(ProceedingJoinPoint pjp) throws Throwable {
            logger.debug("执行监听器: {}.{}", 
                       pjp.getTarget().getClass().getSimpleName(),
                       pjp.getSignature().getName());
            return pjp.proceed();
        }
    }
    

9. 总结

Spring Boot事件机制为应用程序提供了一种强大的解耦通信方式,通过事件驱动架构可以实现组件间的松耦合交互。本文详细介绍了Spring事件的基础概念、实现方式、高级特性以及最佳实践。

主要要点:

  1. 灵活的事件定义:支持传统ApplicationEvent继承和POJO事件两种方式
  2. 多样的监听方式:支持接口实现和注解声明两种风格
  3. 丰富的处理模式:同步、异步、事务绑定等多种处理模式
  4. 强大的集成能力:与Spring生态深度集成,支持条件处理、顺序控制等

通过合理利用Spring Boot事件机制,可以构建出响应迅速、松耦合、易于扩展的应用程序架构,特别适合于复杂业务场景下的系统设计。

事件驱动架构不仅提升了代码的可维护性,还为系统提供了更好的扩展性和可测试性,是构建现代企业应用的重要设计模式。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2321705.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Oracle 数据库安全评估(DBSAT)简明过程

下载DBSAT 从这里下载。 实际是从MOS中下载&#xff0c;即&#xff1a;Oracle Database Security Assessment Tool (DBSAT) (Doc ID 2138254.1)。 最新版本为3.1.0 (July 2024)&#xff0c;名为dbsat.zip&#xff0c;近45MB。 $ ls -lh dbsat.zip -rw-rw-r-- 1 oracle oins…

【T2I】Divide Bind Your Attention for Improved Generative Semantic Nursing

CODE: GitHub - boschresearch/Divide-and-Bind: Official implementation of "Divide & Bind Your Attention for Improved Generative Semantic Nursing" (BMVC 2023 Oral) ABSTRACT 新兴的大规模文本到图像生成模型&#xff0c;如稳定扩散(SD)&#xff0c;已…

【2025】基于springboot+uniapp的企业培训打卡小程序设计与实现(源码、万字文档、图文修改、调试答疑)

基于 Spring Boot uniapp 的企业培训打卡小程序设计与实现 系统功能结构图如下&#xff1a; 一、课题背景 在当今快节奏的商业环境中&#xff0c;企业培训对于员工的成长和企业的发展至关重要。为了满足企业对高效培训管理和员工便捷学习的需求&#xff0c;基于 Spring Boot …

探索AI的无限可能,体验智能对话的未来,大模型 API 演示

探索AI的无限可能&#xff0c;体验智能对话的未来&#xff0c;大模型 API 演示 效果展示&#xff1a; 项目概述 这是一个基于 Vue 3 TypeScript Vite 构建的 Vista AI 演示项目&#xff0c;旨在提供一个简洁易用的界面来展示 Vista AI 大语言模型的能力。项目包含 API 演示…

26考研——图_图的存储(6)

408答疑 文章目录 二、图的存储图的存储相关概念邻接矩阵存储方式邻接矩阵的定义顶点的度计算邻接矩阵的特点邻接矩阵的局限性 应用场景邻接矩阵的幂次意义&#xff08;了解即可&#xff09; 邻接表存储方式邻接表定义邻接表结构邻接表的特点 邻接矩阵和邻接表的适用性差异十字…

datawhale组队学习--大语言模型—task4:Transformer架构及详细配置

第五章 模型架构 在前述章节中已经对预训练数据的准备流程&#xff08;第 4 章&#xff09;进行了介绍。本章主 要讨论大语言模型的模型架构选择&#xff0c;主要围绕 Transformer 模型&#xff08;第 5.1 节&#xff09;、详细 配置&#xff08;第 5.2 节&#xff09;、主流架…

《TCP/IP网络编程》学习笔记 | Chapter 21:异步通知 I/O 模型

《TCP/IP网络编程》学习笔记 | Chapter 21&#xff1a;异步通知 I/O 模型 《TCP/IP网络编程》学习笔记 | Chapter 21&#xff1a;异步通知 I/O 模型同步与异步同步异步对比同步 I/O 的缺点异步 I/O 的优点 理解异步通知 I/O 模型实现异步通知 I/O 模型WSAEventSelect 函数和通知…

Qt6相对Qt5的主要提升(AI总结)

我&#xff1a; Qt 6 相对于5 有哪些新功能&#xff1f; Qt 6 相对于 Qt 5 有诸多新功能和改进&#xff0c;以下是主要的新增特性&#xff1a; 1. 架构和核心库的重构 模块化设计&#xff1a;Qt 6 采用了更加灵活的模块化设计&#xff0c;开发者可以按需引入必要的功能模块&a…

MyBatis操作数据库进阶——动态SQL

动态 SQL 是根据程序运行时的条件灵活生成不同 SQL 语句‌的技术。它的核心目的是在不修改代码‌ 的前提下&#xff0c;通过条件判断、循环等逻辑&#xff0c;动态拼接 SQL 片段&#xff0c;解决传统 SQL 语句死板、难以应对复杂业务场景的问题。 一、<if> 标签 先来观…

使用LLama-Factory的简易教程(Llama3微调案例+详细步骤)

引言&#xff1a;一套快速实现 Llama3 中文微调的教程 主要参考&#xff1a;胖虎遛二狗的 B 站教学视频《【大模型微调】使用Llama Factory实现中文llama3微调》 ✅ 笔者简介&#xff1a;Wang Linyong&#xff0c;西工大&#xff0c;2023级&#xff0c;计算机技术 研究方向&am…

LabVIEW发电平台数据采集系统

本文详细介绍了基于LabVIEW的摇臂式波浪发电平台数据采集系统的设计与实现。通过整合LabVIEW软件与多种传感器技术&#xff0c;本系统能够有效提升数据采集的准确性和效率&#xff0c;为波浪能的利用和发电设备的优化提供科学依据。 ​ 项目背景 随着全球能源需求增长和环境保…

气象可视化卫星云图的方式:方法与架构详解

气象卫星云图是气象预报和气候研究的重要数据来源。通过可视化技术,我们可以将卫星云图数据转化为直观的图像或动画,帮助用户更好地理解气象变化。本文将详细介绍卫星云图可视化的方法、架构和代码实现。 一、卫星云图可视化方法 1. 数据获取与预处理 卫星云图数据通常来源…

【蓝桥杯】每日练习 Day7

目录 前言 领导者 分析 代码 空调 分析 代码 面包店 分析 代码 前言 今天是第一部分的最后一天&#xff08;主打记忆恢复术和锻炼思维&#xff09;&#xff0c;从明天开始主播会逐步更新从位运算到dp问题的常见题型。 领导者&#xff08;分类讨论&#xff09; 分析 …

本地部署Stable Diffusion生成爆火的AI图片

直接上代码 Mapping("/send") Post public Object send(Body String promptBody) { JSONObject postSend new JSONObject(); System.out.println(promptBody); JSONObject body JSONObject.parseObject(promptBody); List<S…

从国家能源到浙江交通投资,全息技术在能源交通领域的创新应用

一、3D全息技术行业应用参数及设计制作要求 全息投影 全息投影技术通过激光器、全息片等设备&#xff0c;将物体的三维信息记录下来&#xff0c;并在特定条件下再现。应用参数包括投影距离、投影面积、投影亮度等。设计制作要求&#xff1a;高清晰度、高亮度、低噪音、稳定性好…

PageHiOffice网页组件(WebOffice文档控件)开发集成技巧专题一

PageHiOffice网页组件作为最新一代的WebOffice文档控件&#xff0c;这是目前市场上唯一能做到在Chrome等最新版浏览器中实现内嵌网页运行的商用文档控件&#xff0c;是OA及ERP等系统处理各种文档的福音。从发布到完善已经超过3年&#xff0c;不管是功能性还是稳定性都已经有了长…

本地安装deepseek大模型,并使用 python 调用

首先进入 ollama 官网 https://ollama.com/点击下载 下载完成后所有都是下一步&#xff0c;就可以 点击搜索 Models &#xff1a; https://ollama.com/search然后点击下载&#xff1a; 选择后复制: ollama run deepseek-r1:32b例如&#xff1a; 让它安装完成后&#xff1…

Android:蓝牙设置配套设备配对

一、概述 在搭载 Android 8.0&#xff08;API 级别 26&#xff09;及更高版本的设备上&#xff0c;配套设备配对会代表您的应用对附近的设备执行蓝牙或 Wi-Fi 扫描&#xff0c;而不需要 ACCESS_FINE_LOCATION 权限。这有助于最大限度地保护用户隐私。使用此方法执行配套设备&am…

Python 变量作用域、global 关键字与闭包作用域深度解析 第三部分

## 三、闭包作用域的存在原因及适用场景 ### 3.1 闭包作用域存在的原因 #### 3.1.1 数据封装与隐藏 闭包可以把数据封装在外部函数的作用域中&#xff0c;只有内部函数能够访问这些数据&#xff0c;这有助于实现数据的隐藏和保护。 python def counter(): count 0 def incre…

zookeeper使用

下载 官网 链接 1. 2. 然后解压&#xff1a; 启动 先复制一份这个文件&#xff0c; 双击启动 默认占用8080&#xff0c;和Tomcat冲突&#xff0c; 解决方法&#xff1a;链接 然后重启