Backend Development 12 min read

Design and Implementation of a Generic Asynchronous Processing SDK for Spring Applications

This article introduces a Spring‑based asynchronous processing SDK that leverages annotations, transaction event listeners, Kafka, XXL‑Job, and a dedicated database to achieve non‑blocking execution, fault tolerance, and eventual consistency while preserving transaction integrity and providing a clear configuration and usage guide.

Top Architect
Top Architect
Top Architect
Design and Implementation of a Generic Asynchronous Processing SDK for Spring Applications

In modern systems, adhering to the Open‑Closed Principle while continuously iterating business logic can increase error rates; to mitigate this, the author designed a generic asynchronous processing SDK that allows developers to offload work to a thread pool without compromising performance or data integrity.

Purpose : Ensure that asynchronous methods execute reliably without blocking the main flow and guarantee data persistence through fallback mechanisms, achieving eventual consistency.

Advantages : Non‑intrusive design with independent database, scheduler, message queue, and UI (single sign‑on). Uses Spring transaction event mechanism so failures in async handling do not affect business logic. Executes after transaction commit/rollback, ensuring data consistency. Provides fallback execution unless both DB and MQ are unavailable.

Principle : After Spring finishes bean initialization, it scans all methods for the @AsyncExec annotation and caches them. At runtime, an AOP aspect publishes an event, and a @TransactionalEventListener processes the asynchronous execution based on the transaction phase.

@TransactionalEventListener(fallbackExecution = true, phase = TransactionPhase.AFTER_COMPLETION)

The listener respects the fallbackExecution=true flag to handle events even when no transaction is active, and processes events both after commit and rollback ( TransactionPhase.AFTER_COMPLETION ).

Components : Kafka message queue XXL‑Job scheduler MySQL database Spring AOP aspect Vue front‑end UI

Design Patterns employed include Strategy, Template Method, Dynamic Proxy, and Flowchart representation.

Database Scripts define three tables: async_scene (scene definitions), async_req (request records), and async_log (execution logs). The scripts create indexes for fast lookup and enforce uniqueness on application_name + method_sign .

CREATE TABLE `async_scene` (
  `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键ID',
  `application_name` varchar(100) NOT NULL DEFAULT '' COMMENT '应用名称',
  `method_sign` varchar(50) NOT NULL DEFAULT '' COMMENT '方法签名',
  `scene_name` varchar(200) NOT NULL DEFAULT '' COMMENT '业务场景描述',
  `async_type` varchar(50) NOT NULL DEFAULT '' COMMENT '异步策略类型',
  `queue_name` varchar(200) NOT NULL DEFAULT '' COMMENT '队列名称',
  `theme_value` varchar(100) NOT NULL DEFAULT '' COMMENT '消费主题',
  `exec_count` int NOT NULL DEFAULT '0' COMMENT '失败重试次数',
  `exec_deleted` int NOT NULL DEFAULT '0' COMMENT '执行后是否删除',
  `async_version` varchar(50) NOT NULL DEFAULT '' COMMENT '组件版本号',
  `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '更新时间',
  `cdc_crt_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '记录新增时间',
  `cdc_upd_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '记录修改时间',
  PRIMARY KEY (`id`) USING BTREE,
  UNIQUE KEY `uk_application_sign` (`application_name`,`method_sign`) USING BTREE,
  KEY `idx_cdc_upd_time` (`cdc_upd_time`)
) ENGINE=InnoDB COMMENT='异步场景表';

Asynchronous Strategy defines execution policies, security levels, and status codes, illustrated with flowcharts (images omitted).

Apollo Configuration (example):

# Switch (default off)
async.enabled=true

# Application name
spring.application.name=xxx

# DataSource (Druid)
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/fc_async?... 
spring.datasource.username=user
spring.datasource.password=xxxx

# Thread pool defaults
async.executor.thread.corePoolSize=10
async.executor.thread.maxPoolSize=50
async.executor.thread.queueCapacity=10000
async.executor.thread.keepAliveSeconds=600

# Delete record after success
async.exec.deleted=true

# Queue name prefix (default app name)
async.topic=${spring.application.name}

# Retry settings
async.exec.count=5
async.retry.limit=100
async.comp.limit=100

# Login interception (default false)
async.login=false

Usage : Enable the async switch: scm.async.enabled=true Annotate methods with @AsyncExec(type = AsyncExecEnum.SAVE_ASYNC, remark = "Data Dictionary") (must be Spring‑proxied). Access the manual handling UI at http://localhost:8004/async/index.html .

Notes : Ensure the Spring application name is correctly set. Queue name defaults to ${async.topic:${spring.application.name}}_async_queue . Business logic must be idempotent. One queue per application; the system handles self‑consumption. Two scheduled tasks: retry every 2 minutes and compensation every hour.

The article concludes with a link to the source code repository ( https://github.com/xiongyanokok/fc-async ) and an invitation for discussion.

backendJavaDatabaseSpringasynchronousKafkaDesign Pattern
Top Architect
Written by

Top Architect

Top Architect focuses on sharing practical architecture knowledge, covering enterprise, system, website, large‑scale distributed, and high‑availability architectures, plus architecture adjustments using internet technologies. We welcome idea‑driven, sharing‑oriented architects to exchange and learn together.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.