@Async+线程池实现异步操作

Spring 的 @Async 注解结合线程池,可实现方法异步执行,将耗时任务交由后台线程处理,避免阻塞主线程。通过自定义 ThreadPoolTaskExecutor 可灵活控制线程资源,常用于发送通知、日志记录、数据同步等非实时操作场景。
  • 异步执行:使用 @Async 和自定义线程池(ThreadPoolTaskExecutor)处理异步业务逻辑,确保主线程快速返回。

  • 统一异常处理:通过实现 AsyncConfigurer 接口,在 getAsyncUncaughtExceptionHandler() 方法中返回自定义的异常处理器(CustomAsyncExceptionHandler)。该处理器捕获所有未被 try-catch 捕获的异步异常,并将错误日志持久化到 MongoDB,同时记录日志。

  • 职责分离:业务方法中仅关注核心逻辑,而异常处理与日志记录均由全局统一机制处理,避免代码重复,提高系统可维护性。

异步线程池配置:AsyncConfig类

/**
 * 异步线程池配置
 */
@Configuration
@EnableAsync
public class AsyncConfig implements AsyncConfigurer {

    @Override
    public Executor getAsyncExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(5);
        executor.setMaxPoolSize(10);
        executor.setQueueCapacity(100);
        executor.setThreadNamePrefix("AsyncExecutor-");
        executor.initialize();
        return executor;
    }

    @Override
    public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
        return new CustomAsyncExceptionHandler();
    }
}

 自定义异步异常处理器:CustomAsyncExceptionHandler

/**
 * 自定义异步异常处理器
 */
@Component
public class CustomAsyncExceptionHandler implements AsyncUncaughtExceptionHandler {

    private static final Logger logger = LoggerFactory.getLogger(CustomAsyncExceptionHandler.class);

    @Autowired
    private MongoTemplate mongoTemplate;

    @Override
    public void handleUncaughtException(Throwable ex, Method method, Object... params) {
        // 构建错误日志对象
        AsyncErrorLog errorLog = new AsyncErrorLog();
        errorLog.setMethodName(method.getName());
        errorLog.setParameters(Arrays.toString(params));
        errorLog.setExceptionMessage(ex.getMessage());
        errorLog.setStackTrace(ExceptionUtils.getStackTrace(ex));
        errorLog.setTimestamp(LocalDateTime.now());

        // 保存至 MongoDB
        try {
            mongoTemplate.save(errorLog, "async_error_logs");
        } catch (Exception mongoEx) {
            logger.error("保存异步错误日志到 MongoDB 失败:{}", mongoEx.getMessage(), mongoEx);
        }

        // 记录日志
        logger.error("异步方法 '{}' 发生异常:{}", method.getName(), ex.getMessage(), ex);
    }
}

异步服务类:AsyncService

@Service
public class AsyncService {

    private static final Logger logger = LoggerFactory.getLogger(AsyncService.class);

    /**
     * 异步任务示例方法,使用自定义线程池 "taskExecutor" 执行。
     * 此方法内部模拟了耗时操作和可能发生的异常,用于验证全局异常处理机制。
     */
    @Async("taskExecutor")
    public void performAsyncTask() {
        logger.info("【开始执行异步任务】当前线程:{}", Thread.currentThread().getName());
        // 异步执行 todo

        logger.info("【异步任务执行完毕】当前线程:{}", Thread.currentThread().getName());
    }
}

 

posted @ 2025-04-16 09:10  ~落辰~  阅读(79)  评论(0)    收藏  举报