Skip to main content
Yanked

This release has been yanked by its maintainers, and will be ignored by installers, except when explicitly specified.
Consider using release 2.3.2 instead.

SpringBootAI 综合使用指南

SpringBootAI 是一个借鉴 Spring Boot 编程模型的 Python Web 框架,提供装饰器式组件扫描、依赖注入、FastAPI 路由、配置加载、安全能力、内嵌的 PyMyBatis ORM,以及企业级 AI 模块(对齐 Spring AI 2.0:ChatClient/Advisor/Tools/RAG/Function Calling)。本指南为框架核心综合使用文档;AI / ORM / Cloud / Excel 等模块的完整注解与功能说明已分离为独立文档(见下方“模块文档”),本指南相应章节保留概览与跳转链接。

  • SpringBootAI 版本:1.8.2
  • 内嵌 PyMyBatis 版本:1.4.0
  • Python:3.10+
  • 状态:Beta(企业试点)
  • 仓库:GitHub - YUCONGGEN/springbootAI
  • License:MIT

模块文档

各模块的注解参考与功能说明已从本指南分离为独立文档,按需查阅:

模块 文档 安装 说明
AI(对齐 Spring AI 2.0) AI_MODULE.md pip install springbootAI[ai] ChatClient / Advisor / Tools / RAG / Function Calling / ETL / 多厂商 LangChain 化 / 韧性 / 观测
内嵌 PyMyBatis ORM 与 DDL ORM_MODULE.md 随核心包 Mapper 注解 / XML Mapper / 分页 / SQL 安全 / DDL 自动建表
Spring Cloud(对齐 Cloud Alibaba) CLOUD_MODULE.md 随核心包 服务注册发现 / 配置刷新 / Feign / Sentinel / Gateway / 负载均衡 / 分布式事务
Excel(对齐 alibaba EasyExcel) EXCEL_MODULE.md pip install springbootAI[excel] @ExcelProperty / @ExcelIgnore / @excel_sheet 注解驱动读写
CSV(注解驱动读写) CSV_MODULE.md pip install springbootAI[csv] @CsvProperty / @CsvIgnore / @csv_file 注解驱动读写 / 转换器 / 流式
Swagger / OpenAPI(对齐 SpringDoc) SWAGGER_MODULE.md 随核心包 @Tag / @Operation / @ApiResponse / @Parameter / @Schema / @SecurityScheme 注解驱动 API 文档 + Swagger2 别名
P0/P1/P2 八大模块 EIGHT_MODULES.md 随核心包 Spring Data Repository / Actuator / 多数据源读写分离 / 事务事件 / 配置松散绑定 / 测试切片 / i18n / WebSocket
安全 SECURITY.md 随核心包 JWT 生成校验 / 密码加密(SHA256/MD5/BCrypt)/ SQL 注入防护 / 访问控制
BeanUtils(属性复制工具) BEAN_UTILS.md 随核心包 copy_properties / clone / get_property / set_property / populate / describe 对齐 Spring + Apache Commons BeanUtils
测试报告 TEST_REPORT.md 全量测试用例与覆盖范围

所有模块文档统一存放于 doc/ 目录。本指南正文中出现的"已分离至独立文档"链接均指向 doc/ 下的对应文件。

目录

  1. 框架概述与定位
  2. 能力状态
  3. 安装与快速开始
  4. 配置系统
  5. 注解参考
  6. IoC 与依赖注入
  7. Web 控制器
  8. 内嵌 PyMyBatis ORM 与 DDL
  9. 事务
  10. 安全与权限
  11. 缓存、任务与高级 AOP
  12. SpringBootAI AI 模块
  13. Java 迁移指南
  14. 生产部署
  15. 项目结构
  16. 测试
  17. 常见问题与排错
  18. 性能与容量验证

1. 框架概述与定位

SpringBootAI 借鉴了 Spring Boot 的注解和分层习惯,但运行时是 Python、FastAPI 和 Uvicorn。它不兼容 Java 字节码、Spring Bean 后处理器、JPA、Java MyBatis 插件或 Maven/Gradle 生态。

1.1 版本

组件 当前版本
spring 框架 API 1.8.2
spring.orm.pymybatis 1.4.0
Python 3.10+

1.2 推荐使用范围

  • 内部管理接口、轻量业务服务、教学和原型验证。
  • 希望统一使用控制器/服务/Mapper 分层方式的 Python 团队。
  • SQLite 本地工具,或经过目标数据库集成测试的受控服务。
  • 微服务架构(内置服务发现、限流熔断、分布式追踪、分布式事务)。

1.3 能力边界

  • 自动化 ORM 契约测试使用 SQLite;MySQL、PostgreSQL、Oracle 需单独验证。
  • 本地 @Transactional 支持全部七种 Spring 传播模式;REQUIRES_NEWNOT_SUPPORTED 需要连接池有额外可用连接。
  • Profile 会筛选 @Profile Bean,但不会自动合并 application-{profile}.yml
  • Nacos、RabbitMQ、Prometheus 依赖外部服务;Sentinel 和 OpenTelemetry 追踪可内嵌运行。HTTP 事务模式是持久化补偿协调器,不提供 Seata AT 强一致性;生产强一致场景必须使用真实 Seata Server 或可靠消息方案。
  • 限流、分布式锁、幂等和缓存语义依赖 Redis 等后端,降级路径需要故障注入。

1.4 注解使用总览

SpringBootAI 注解会先把元数据放到 __spring_annotations__。之后是否生效,取决于是否存在对应的扫描器或切面:

状态 含义
容器执行 ApplicationContextBeanFactory 或 Web 上下文会读取并执行
受管 Bean 执行 只有被组件扫描并由容器创建的实例方法才会被 AOP 包装;自己 ClassName() 创建的对象不生效
直接执行 装饰器本身返回包装函数,不依赖 IoC 容器
仅元数据 当前有注解类,但主运行链路没有消费者,写上不会得到注解名字所暗示的功能

这也是 SpringBootAI 与 Java Spring 最容易混淆的地方:名称相似不代表参数和运行语义完全相同。


2. 能力状态

模块 状态 说明
IoC 容器 ✅ 可用 组件扫描、构造器/字段注入、Bean、延迟初始化、生命周期回调、Profile 过滤
Web MVC ✅ 可用 基于 FastAPI 的 GET/POST/PUT/PATCH/DELETE 路由、参数绑定、异常处理、CORS 和静态文件
配置 ✅ 可用 YAML、${ENV:default}、固定环境变量覆盖、标量类型保留;全局加载器与应用上下文共享配置路径和状态
应用事件 ✅ 可用 ApplicationEvent@EventListener、同步有序发布和异步监听方法调度
内嵌 ORM + DDL Auto ✅ 可用 PyMyBatis + JPA ddl-auto 自动建表(create/update/validate),支持 XML/注解 SQL、事务、缓存
本地事务 ✅ 可用 @Transactional 支持七种 Spring 传播模式;REQUIRES_NEW/NOT_SUPPORTED 需要连接池可提供额外连接
JWT 与方法安全 ✅ 可用 access/refresh token、@Authenticate、角色/权限授权、401/403 映射和并发上下文隔离
重试/异步 ✅ 可用 受管 Bean 的退避重试、恢复方法和 Future/Task 异步调度
Redis/缓存 ✅ 可用 分布式锁、KV/Hash/List/Set/Counter,需要 Redis 服务
RabbitMQ ✅ 可用 @RabbitListener 自动注册并后台消费,RabbitTemplate 发送
Nacos 服务发现 ✅ 可用 服务注册/发现/订阅,支持无认证开发模式
Sentinel 限流熔断 ✅ 可用 内嵌引擎,QPS 限流、异常比例/异常数/慢调用熔断、热点参数限流,无需 Dashboard
分布式追踪 ✅ 可用 原生 OpenTelemetry(W3C traceparent),自动 HTTP/Feign 注入,无需 OAP Server
Seata 分布式事务 ⚠️ 有边界 distributed 对接真实 Seata SDK/Server;http 仅提供显式启用的持久化补偿,支持重启恢复和 XID 传播,不等同 AT
API Gateway ✅ 可用 轻量 ASGI/WSGI 网关,路由转发、路径重写、过滤器链、负载均衡
Prometheus 监控 ✅ 可用 Counter/Gauge/Histogram 指标暴露
Feign 声明式 HTTP ✅ 可用 声明式接口、Fallback 降级、自动传播 XID 和 trace 头
高级 AOP ✅ 可用 限流、熔断、幂等、审计、锁、指标、追踪、缓存
SpringBootAI AI 模块 ✅ 可用 对齐 Spring AI 2.0:ChatClient/ChatModel/EmbeddingModel/Advisor/Tools,OpenAI/Ollama/DeepSeek/Moonshot 适配,Function Calling 闭环、RAG、会话记忆、Redis 向量存储、熔断重试、真流式 async、Prometheus 观测、类型化配置绑定

3. 安装与快速开始

3.1 环境准备

cd springboot
python -m venv .venv

激活虚拟环境:

# PowerShell
.\.venv\Scripts\Activate.ps1
# Linux/macOS
source .venv/bin/activate

3.2 安装框架

python -m pip install --upgrade pip
python -m pip install -e .

核心依赖包含 FastAPI、Uvicorn、PyYAML、python-dotenv、DBUtils、PyJWT、cryptography、bcrypt 和 Pydantic。核心安装已包含内嵌 spring.orm.pymybatis,使用 Mapper 模式不需要再安装独立 pymybatis

3.3 可选 extras

python -m pip install -e ".[mysql]"             # PyMySQL
python -m pip install -e ".[postgresql]"        # psycopg2-binary
python -m pip install -e ".[oracle]"            # cx-Oracle
python -m pip install -e ".[sqlalchemy]"        # SQLAlchemy 模式
python -m pip install -e ".[redis]"             # Redis 能力
python -m pip install -e ".[ast]"               # sqlglot AST 校验
python -m pip install -e ".[rabbitmq]"          # pika
python -m pip install -e ".[nacos]"             # Nacos 客户端
python -m pip install -e ".[prometheus,logging]" # 指标和 loguru
python -m pip install -e ".[dev]"               # 测试和静态工具

AI 模块为可选依赖(未安装时降级原生 HTTP + FakeChatModel):

pip install -r requirements-ai.txt   # langchain-openai/langchain-community/numpy(==锁版本)

requirements.txt 是仓库的完整开发环境,包含多种数据库和中间件客户端。应用接入时优先按需安装 extras。

3.4 验证安装

python -c "import spring; print(spring.__version__)"
python -c "from spring.orm.pymybatis import __version__; print(__version__)"

3.5 最小应用

仓库中的 exampleexample1example5 只用于源码参考和回归验证,不会打包进 springbootAI。安装后请按下面结构创建自己的应用包,不要从 site-packages 导入这些示例。每个被扫描目录都必须包含 __init__.py,并从项目根目录启动。

创建包结构:

demo/
|-- __init__.py
|-- Application.py
|-- application.yml
`-- controller/
    |-- __init__.py
    `-- HelloController.py

创建 demo/Application.py

from spring.annotations import SpringBootApplication
from spring.main import run


@SpringBootApplication(scan_base_packages=["demo"])
class Application:
    pass


if __name__ == "__main__":
    run(Application)

创建 demo/controller/HelloController.py

from spring.annotations import GetMapping, RequestMapping, RestController


@RequestMapping("/api")
@RestController
class HelloController:
    @GetMapping("/hello/{name}")
    def hello(self, name: str):
        return {"message": f"Hello, {name}"}

创建 demo/application.yml

server:
  host: 127.0.0.1
  port: 8080
  cors:
    allow_origins: []
    allow_credentials: false

redis:
  enabled: false

database:
  enabled: false

jwt:
  secret_key: development-only-secret
  algorithm: HS256

运行和验证:

python -m demo.Application
curl http://127.0.0.1:8080/api/hello/Alice
curl http://127.0.0.1:8080/actuator/health/liveness
curl http://127.0.0.1:8080/actuator/info

默认响应会统一包装为 Result

{
  "code": 200,
  "message": "success",
  "data": {"message": "Hello, Alice"}
}

交互式 API 文档由 FastAPI 提供,默认访问 http://127.0.0.1:8080/docs;原始规范位于 /openapi.json

3.6 生产 ASGI 入口

开发时可以使用 run();生产进程管理应使用 create_app() 构建 ASGI 应用:

# asgi.py
from spring.main import create_app
from demo.Application import Application

app = create_app(Application)
uvicorn asgi:app --host 0.0.0.0 --port 8080 --workers 2

多 worker 会创建多个独立进程、IoC 容器和连接池。连接池总量应按 worker 数 x max_size 评估。


4. 配置系统

4.1 配置位置

ApplicationContext 按以下顺序查找配置:

  1. 启动类文件所在目录的 application.yml
  2. 启动类目录下的 config/application.yml
  3. 两处都不存在时使用代码默认值和环境变量。

两处都存在时第一项优先,不会合并。仓库自带的 example 使用第二种目录布局。

ApplicationContext 启动后会把该路径绑定到稳定的全局加载器,之后新建的 ConfigLoader() 也读取同一文件,不再依赖进程当前工作目录。

4.2 环境变量占位符

server:
  port: ${SERVER_PORT:8080}
database:
  enabled: ${DB_ENABLED:false}
  password: ${DB_PASSWORD}
  • ${NAME}:环境变量必填,未设置时报 ConfigurationError
  • ${NAME:default}:未设置时使用默认值。
  • 占位符占满整个值时,YAML 会把 8080falsenull 保留为 int、bool、None(完整占位符会保留标量类型)。
  • 占位符嵌入普通字符串时结果仍是字符串。

4.3 固定覆盖变量

除 YAML 占位符外,加载器还会读取固定变量:

分类 环境变量
服务 SERVER_HOSTSERVER_PORT
环境 SPRING_PROFILES_ACTIVESTARTUP_FAIL_FAST
JWT JWT_SECRET_KEYJWT_ALGORITHM
数据库 DB_ENABLEDDB_URLDB_HOSTDB_PORTDB_NAMEDB_USERNAMEDB_PASSWORDDB_DRIVER
Redis REDIS_ENABLEDREDIS_HOSTREDIS_PORTREDIS_DBREDIS_PASSWORD
CORS CORS_ALLOW_ORIGINSCORS_ALLOW_CREDENTIALS
日志 LOG_LEVELLOG_DIRLOG_RETENTIONLOG_ROTATION
中间件 DISCOVERY_*NACOS_SERVERNACOS_USERNAMENACOS_PASSWORDSEATA_*RABBITMQ_*PROMETHEUS_*
Docker 辅助 SPRING_DISABLE_DOCKER_IP_DETECT(设为 1 禁用容器 IP 自动检测)

database.driverdatabase.database、连接池和 ORM 安全参数,推荐直接在 YAML 中使用 ${DB_DRIVER:...} 等占位符。

常用覆盖变量示例:

SPRING_PROFILES_ACTIVE  STARTUP_FAIL_FAST
SERVER_HOST             SERVER_PORT
JWT_SECRET_KEY          JWT_ALGORITHM
DB_ENABLED              DB_URL
REDIS_ENABLED           REDIS_HOST        REDIS_PORT
DISCOVERY_ENABLED       NACOS_SERVER      NACOS_NAMESPACE
NACOS_GROUP             NACOS_USERNAME    NACOS_PASSWORD
CORS_ALLOW_ORIGINS      CORS_ALLOW_CREDENTIALS
LOG_LEVEL               LOG_DIR

当前 SPRING_PROFILES_ACTIVE 用于 @Profile 组件筛选和生产安全校验,不会自动合并 application-prod.yml。需要多环境文件时,由部署流程生成最终 application.yml 或显式传入配置路径。

4.4 Docker 容器 IP 自动检测(开发环境)

在开发环境中,当 database.host 设为 127.0.0.1localhost 时,框架会自动通过 docker psdocker inspect 查找映射了目标端口的容器内部 IP 进行连接,无需手动配置容器 IP。

  • 支持通过端口映射精确匹配(如 0.0.0.0:3306->3306/tcp
  • 支持 MySQL/MariaDB/PostgreSQL 数据库镜像兜底匹配
  • 设置 SPRING_DISABLE_DOCKER_IP_DETECT=1 可禁用此功能(生产环境推荐)

4.5 读取配置

from spring.config import ConfigLoader

loader = ConfigLoader("./myapp/application.yml")
port = loader.get("server.port", 8080)
database = loader.get_prefix_config("database")
snapshot = loader.get_config()

返回的配置是深拷贝,调用方修改不会回写加载器。需要加载另一份配置时,显式传入 config_pathbase_path

4.6 Profile 的真实行为

spring:
  profiles:
    active: dev
from spring.annotations import Profile, Service


@Profile("dev")
@Service
class DevelopmentService:
    pass

Profile 用于 Bean 过滤和生产安全校验。当前实现不会自动读取、合并 application-dev.ymlapplication-prod.yml。多环境配置可使用以下方式之一:

  1. 在部署流程中生成最终 application.yml
  2. 大量使用环境变量占位符。
  3. 在自定义启动代码中显式创建 ConfigLoader(config_path=...)ApplicationContext

4.7 生产配置校验

当 Profile 是 prodproduction 时:

  • 默认 JWT 密钥、空密钥或少于 32 字符的密钥会导致启动失败。
  • startup.fail_fast 默认视为开启。
  • CORS 开启凭证时配置 * 来源会直接失败。

4.8 健康检查

地址 用途
/actuator/health 聚合组件健康状态;降级时返回 503
/actuator/health/liveness 进程存活检查
/actuator/health/readiness 服务就绪检查
/actuator/info 应用名称、当前 Profile、框架和 Python 版本

聚合健康非 UP 时返回 HTTP 503。组件检查带超时,避免单个依赖长期阻塞健康端点。database.enabled: false 时数据库状态为 DISABLED,不会初始化默认 SQLite、不会创建 test.db,也不会虚报为 UP。生产探针应区分 liveness 和 readiness,避免依赖组件短暂故障导致进程反复重启。


5. 注解参考

说明:本节的注解参数表格是框架最完整的参考(来源自注解使用指南)。各注解的"当前行为与边界"信息(来源自使用说明书)已在表格下补充。所有 AOP 类注解(事务、缓存、重试、异步、定时、高级 AOP、安全等)都要求方法所在类带组件注解(@Service/@Component/@Repository/@Controller 等)并由容器取得实例,自己 ClassName() 创建的对象不会生效。

5.1 启动与扫描

@SpringBootApplication

含义:Spring Boot 应用启动类注解,组合了 @Configuration@ComponentScan 的功能。

参数

参数 类型 默认值 说明
scan_base_packages List[str] None 扫描的基础包路径

用法示例

from spring.annotations import SpringBootApplication

@SpringBootApplication(scan_base_packages=["com.example.service", "com.example.controller"])
class Application:
    pass

注意事项

  • 每个应用只能有一个启动类;不指定 scan_base_packages 时默认扫描启动类所在包及其子包。
  • scan_base_packages 是可导入包名,不是文件路径。

@ComponentScan

参数

参数 类型 默认值 说明
base_packages List[str] None 扫描的基础包路径
from spring.annotations import Configuration, ComponentScan

@Configuration
@ComponentScan(base_packages=["com.example.service", "com.example.dao"])
class AppConfig:
    pass

边界:容器执行;不要和带 scan_base_packages 的启动注解重复配置。

5.2 组件与依赖注入

@Component

参数value(str,默认 "",Bean 名称)

from spring.annotations import Component

@Component
class EmailUtil:
    def send(self, to: str, content: str):
        pass

@Service

参数value(str,默认 "",Bean 名称,默认使用类名首字母小写)

from spring.annotations import Service

@Service
class UserService:
    def get_user(self, user_id: int):
        return {"id": user_id, "name": "test"}

边界:行为与 @Component 相同,名称表达业务层语义。

@Repository

参数value(str,默认 ""

from spring.annotations import Repository

@Repository
class UserRepository:
    def find_by_id(self, user_id: int):
        pass

边界:行为与 @Component 相同;它不是 ORM Mapper 注解

@Autowired

参数required(bool,默认 True;为 False 时找不到 Bean 不会报错)

from spring.annotations import Service, Autowired

@Service
class UserService:
    # 构造函数注入(推荐)
    @Autowired
    def __init__(self, user_repository):
        self.user_repository = user_repository

边界:推荐构造器注入;required=False 当前不会把缺失依赖自动变成 None。依赖参数应写类型注解,构造器注入能在启动阶段暴露缺失和循环依赖。

@Qualifier

参数value(str,必填,Bean 名称)

from spring.annotations import Service, Autowired, Qualifier

@Service
class OrderService:
    @Autowired
    def __init__(self, @Qualifier("mysqlDataSource") data_source):
        self.data_source = data_source

边界:当前是方法级元数据,不是 Java 那种逐参数注解;复杂多歧义依赖宜拆分或用明确类型。

@Primary

含义:当有多个同类型 Bean 时标记首选 Bean。

from spring.annotations import Configuration, Bean, Primary

@Configuration
class DataSourceConfig:
    @Bean
    @Primary
    def primary_data_source(self):
        return {"url": "jdbc:mysql://primary:3306/db"}

    @Bean
    def secondary_data_source(self):
        return {"url": "jdbc:mysql://secondary:3306/db"}

@Profile

参数value(str 或 List[str],必填,环境名称)

from spring.annotations import Configuration, Bean, Profile

@Configuration
class DataSourceConfig:
    @Bean
    @Profile("dev")
    def dev_data_source(self):
        return {"url": "jdbc:mysql://dev:3306/db"}

    @Bean
    @Profile("prod")
    def prod_data_source(self):
        return {"url": "jdbc:mysql://prod:3306/db"}

边界:容器执行;只筛 Bean,不加载或合并 application-{profile}.yml

@Lazy

参数value(bool,默认 True

from spring.annotations import Service, Lazy

@Service
@Lazy
class HeavyService:
    pass

边界:容器刷新时跳过;首次 get_bean()、依赖注入、控制器注册或任务注册需要它时创建,并在创建时完成配置绑定。

5.3 Web 控制器注解

@Controller / @RestController

参数value(str,默认 "",Bean 名称)

@RestController 组合了 @Controller@ResponseBody,返回值自动序列化为 JSON。

from spring.annotations import RestController, GetMapping

@RestController
class UserController:
    @GetMapping("/api/users/{id}")
    def get_user(self, id: int):
        return {"id": id, "name": "test"}

边界@Controller 当前仍按 JSON/Result 返回,没有 Java MVC 视图模板语义;@RestController(value=...)value 是组件元数据,不会成为路由前缀。

@RequestMapping

参数

参数 类型 默认值 说明
path str | List[str] "" 请求路径
method List[str] [] HTTP 方法:GET, POST, PUT, PATCH, DELETE 等
consumes str None 请求的 Content-Type
produces str None 响应的 Content-Type
from spring.annotations import RestController, RequestMapping

@RestController
@RequestMapping("/api/users")
class UserController:
    @RequestMapping(path="/{id}", method=["GET"])
    def get_user(self, id: int):
        return {"id": id}

边界:类上定义路径前缀;方法上定义路径和 HTTP method 列表。consumesproduces 当前保存但未用于路由约束。

@GetMapping / @PostMapping / @PutMapping / @PatchMapping / @DeleteMapping

参数(以 @GetMapping 为例):

参数 类型 默认值 说明
path str | List[str] "" 请求路径
consumes str None 请求 Content-Type
produces str None 响应 Content-Type
from spring.annotations import RestController, GetMapping, PostMapping, PutMapping, PatchMapping, DeleteMapping

@RestController
class UserController:
    @GetMapping("/api/users/{id}")
    def get_user(self, id: int):
        return {"id": id, "name": "test"}

    @PostMapping("/api/users")
    def create_user(self, name: str, email: str):
        return {"id": 1, "name": name, "email": email}

    @PutMapping("/api/users/{id}")
    def update_user(self, id: int, name: str):
        return {"id": id, "name": name}

    @PatchMapping("/api/users/{id}")
    def patch_user(self, id: int, name: str = ""):
        return {"id": id, "name": name, "method": "PATCH"}

    @DeleteMapping("/api/users/{id}")
    def delete_user(self, id: int):
        return {"status": "deleted", "id": id}

边界

  • 未指定映射路径时默认使用方法名,例如 @GetMapping 标注 list_users 会映射为 /list_users
  • @PatchMapping 框架会注册为真实的 FastAPI PATCH 路由,并纳入默认 CORS 方法。
  • POST/PUT/PATCH/DELETE 普通返回值统一包装为成功 Result

@CrossOrigin

参数

参数 类型 默认值 说明
origins List[str] ["*"] 允许的源
methods List[str] ["GET","POST","PUT","PATCH","DELETE","OPTIONS"] 允许的 HTTP 方法
allowedHeaders List[str] ["*"] 允许的请求头
allowCredentials bool False 是否允许携带凭证
maxAge int 3600 预检请求缓存时间(秒)
from spring.annotations import RestController, GetMapping, CrossOrigin

@RestController
@CrossOrigin(origins=["http://localhost:3000"], allow_credentials=True)
class UserController:
    @GetMapping("/api/users")
    def list_users(self):
        return []

边界:Web 上下文采用找到的第一组,并传递 origins、方法、Header、凭证和 maxAge

@ResponseStatus

参数code(int,必填)、reason(str,默认 ""

from spring.annotations import RestController, PostMapping, ResponseStatus

@RestController
class UserController:
    @PostMapping("/api/users")
    @ResponseStatus(code=201, reason="Created")
    def create_user(self, name: str):
        return {"id": 1, "name": name}

边界:方法级覆盖类级,reason 非空时成为 Result.message

@ControllerAdvice / @ExceptionHandler

from spring.annotations import ControllerAdvice, ExceptionHandler

@ControllerAdvice
class GlobalExceptionHandler:
    @ExceptionHandler(ValueError, TypeError)
    def handle_validation_error(self, e: Exception):
        return {"code": 400, "message": f"参数错误: {str(e)}"}

    @ExceptionHandler(Exception)
    def handle_generic_error(self, e: Exception):
        return {"code": 500, "message": f"服务器错误: {str(e)}"}

边界:当前按异常的精确类型匹配,不自动匹配父类。未处理异常对客户端返回通用 500,不暴露内部堆栈;详细信息写入服务日志。

5.4 参数绑定注解

参数标记的正确语法是"作为默认值"写在方法参数上,而不是写在函数上方。

@RequestParam

参数 类型 默认值 说明
name str None 参数名,默认使用方法参数名
required bool True 是否必须
default Any None 默认值
from spring.annotations import RestController, GetMapping, RequestParam

@RestController
class UserController:
    @GetMapping("/api/users")
    def list_users(
        self,
        page: int = RequestParam(name="page", default=1),
        size: int = RequestParam(name="size", default=10)
    ):
        return {"page": page, "size": size, "data": []}

@PathVariable

参数 类型 默认值 说明
name str None 变量名,默认使用方法参数名
required bool True 是否必须
from spring.annotations import RestController, GetMapping, PathVariable

@RestController
class UserController:
    @GetMapping("/api/users/{id}")
    def get_user(self, id: int = PathVariable(name="id")):
        return {"id": id}

边界:路径中的 {name} 必须与路由对应;当前始终按必填处理。

@RequestBody

参数 类型 默认值 说明
required bool True 是否必须
from spring.annotations import RestController, PostMapping, RequestBody

@RestController
class UserController:
    @PostMapping("/api/users")
    def create_user(self, user_data: dict = RequestBody()):
        return {"id": 1, **user_data}

边界:当前以 dict 为主;RequestBody(required=False) 接受空 body;需要复杂 Pydantic 模型校验时应增加 Web 集成测试。

@RequestHeader

参数 类型 默认值 说明
name str None 请求头名称
required bool True 是否必须
default Any None 默认值
from spring.annotations import RestController, GetMapping, RequestHeader

@RestController
class UserController:
    @GetMapping("/api/user/profile")
    def get_profile(self, token: str = RequestHeader(name="Authorization")):
        return {"token": token}

边界:参数名中的 _ 默认转换为 -

@CookieValue

参数 类型 默认值 说明
name str None Cookie 名称
required bool True 是否必须
default Any None 默认值
from spring.annotations import RestController, GetMapping, CookieValue

@RestController
class UserController:
    @GetMapping("/api/user/theme")
    def get_theme(self, theme: str = CookieValue(name="theme", default="light")):
        return {"theme": theme}

参数绑定规则汇总

写法 来源
参数名出现在 {...} 路径 路径参数
参数类型是 dict JSON 请求体
有普通默认值 可选查询参数
无默认值且不在路径 必填查询参数
默认值为 RequestParam(...) 显式查询参数
默认值为 RequestBody() 显式请求体
默认值为 RequestHeader(...) Header
默认值为 CookieValue(...) Cookie

5.5 配置与属性注解

@Configuration

参数proxyBeanMethods(bool,默认 True

from spring.annotations import Configuration, Bean

@Configuration
class AppConfig:
    @Bean
    def data_source(self):
        return {"url": "jdbc:mysql://localhost:3306/db"}

边界:容器执行;proxyBeanMethods 当前没有特殊代理语义。

@Bean

参数

参数 类型 默认值 说明
name str None Bean 名称,默认使用方法名
scope str "singleton" 作用域:singleton, prototype
init_method str None 初始化方法名
destroy_method str None 销毁方法名
from spring.annotations import Configuration, Bean

@Configuration
class AppConfig:
    @Bean(name="dataSource", init_method="init", destroy_method="close")
    def data_source(self):
        return DataSource()

边界:生产资源应确保销毁方法可重复调用。

@Value

参数value(str,必填,配置键)

from spring.annotations import Service, Value

@Service
class AppService:
    def __init__(self):
        self.app_name = None

    @Value("${app.name}")
    def set_app_name(self, value: str):
        self.app_name = value

边界:支持通过默认参数或字段注解注入配置;使用点号路径(如 server.port),不要照搬 Java 的 ${server.port} 写法:

def __init__(self, port: int = Value("server.port")):
    ...

@ConfigurationProperties

参数prefix(str,必填,配置前缀)

from spring.annotations import ConfigurationProperties, Component

@Component
@ConfigurationProperties(prefix="spring.datasource")
class DataSourceProperties:
    def __init__(self):
        self.url = ""
        self.username = ""
        self.password = ""
        self.driver_class_name = ""

边界:只给对象已有属性赋值,不做完整 Pydantic 校验。对一组配置优先使用它,并为字段提供明确类型和默认值。

5.6 日志与生命周期注解

@Slf4j

参数logger_name(str,默认 None,默认使用类名)

from spring.annotations import Service, Slf4j

@Service
@Slf4j
class UserService:
    def create_user(self, name: str):
        self.logger.info(f"Creating user: {name}")
        return {"id": 1, "name": name}

边界:属性名固定为 logger

@LogExecutionTime

参数log_level(str,默认 "info")

from spring.annotations import Service, LogExecutionTime

@Service
class ReportService:
    @LogExecutionTime(log_level="info")
    def generate_report(self, report_type: str):
        time.sleep(1)
        return {"report": report_type}

边界:直接包装;异步方法统计完整 await 时间,异常时也记录。

@PostConstruct / @PreDestroy

from spring.annotations import Service, PostConstruct, PreDestroy

@Service
class InitService:
    def __init__(self):
        self.config = None

    @PostConstruct
    def init(self):
        # 在所有依赖注入完成后执行
        self.config = self.load_config()

    @PreDestroy
    def cleanup(self):
        # 销毁前清理资源
        if self.connection:
            self.connection.close()

边界@PostConstruct 每个 Bean 初始化时调用一次;@PreDestroy 应用必须走正常关闭流程才有机会执行。应用关闭时会销毁容器资源;ASGI 关闭事件还会关闭 MyBatis SqlSessionFactory 和共享连接池。

5.7 应用事件

ApplicationEvent 是事件基类,@EventListener 标记受管 Bean 的监听方法。ApplicationContext 刷新时会自动扫描监听器,publish_event() 默认按 order 同步调用匹配的监听器;异步监听方法会被调度到当前事件循环或异步执行器。

from spring.annotations import ApplicationEvent, Autowired, EventListener, Service
from spring.event import ApplicationEventPublisher


class UserCreatedEvent(ApplicationEvent):
    def __init__(self, user_id: int):
        super().__init__(source="user-service")
        self.user_id = user_id


@Service
class UserEventHandler:
    @EventListener(event_type=UserCreatedEvent, order=1)
    def on_user_created(self, event: UserCreatedEvent):
        print(f"created: {event.user_id}")


@Service
class UserService:
    @Autowired
    def __init__(self, publisher: ApplicationEventPublisher):
        self.publisher = publisher

    def create(self, user_id: int):
        self.publisher.publish_event(UserCreatedEvent(user_id))

监听方法的第一个事件参数可以省略 event_type,框架会从类型注解推断。监听器必须由容器创建;发布时的监听器异常会返回给发布方,不会静默吞掉。需要隔离失败时应在监听器内部处理异常或使用异步任务。

5.8 核心高级注解(10 个)

@RateLimit - 接口限流

参数

参数 类型 默认值 说明
max_requests int 100 时间窗口内允许的最大请求数
time_window int 60 时间窗口(秒)
key str None 限流键,支持动态参数

Key 动态解析规则:直接写参数名 key="user_id"(按用户 ID 限流);使用占位符 key="ip_{ip}"(组合前缀和参数);不指定则使用方法全限定名作为键。

from spring.annotations import RateLimit, Service

@Service
class OrderService:
    # 每分钟最多100次请求(全局限流)
    @RateLimit(max_requests=100, time_window=60)
    def create_order(self, user_id: str, product_id: str):
        return {"order_id": "ORD_123"}

    # 按用户ID限流,每个用户每秒最多10次
    @RateLimit(max_requests=10, time_window=1, key="user_id")
    def get_user_info(self, user_id: str):
        return {"user_id": user_id}

注意事项:线程安全,支持高并发;存储有大小限制(10000 条),超出自动清理最旧条目;超出限流抛出 Exception: Rate limit exceeded: ...。Redis 不可用时退化为单进程内存计数。

@CircuitBreaker - 熔断器

参数

参数 类型 默认值 说明
failure_threshold int 5 连续失败次数阈值,达到后熔断
recovery_timeout int 30 熔断恢复时间(秒),过后进入半开状态
fallback_method str None 熔断时的降级方法名

状态流转

CLOSED(关闭)→ 失败达到阈值 → OPEN(熔断)
     ↑                        ↓
     ↓  半开状态成功     等待recovery_timeout
HALF_OPEN(半开) ←───────────┘
from spring.annotations import CircuitBreaker, Service

@Service
class PaymentService:
    @CircuitBreaker(failure_threshold=3, recovery_timeout=10, fallback_method="payment_fallback")
    def process_payment(self, order_id: str, amount: float):
        if amount > 10000:
            raise Exception("Payment gateway timeout")
        return {"status": "success", "transaction_id": "TXN_123"}

    def payment_fallback(self, order_id: str, amount: float):
        return {"status": "degraded", "message": "Payment service unavailable, please try again later"}

注意事项:降级方法必须定义在同一个类中,参数列表必须与原方法完全一致;半开状态下调用成功自动恢复到关闭状态。Redis 不可用时状态仅在当前进程。

@Idempotent - 幂等性

参数

参数 类型 默认值 说明
key str None 幂等键参数名,如 "order_id",支持占位符
expire int 300 幂等结果缓存时间(秒)
prefix str "idempotent" 键前缀,用于区分不同业务
from spring.annotations import Idempotent, Service

@Service
class OrderService:
    @Idempotent(key="order_id", expire=300, prefix="order")
    def create_order(self, order_id: str, user_id: str, amount: float):
        return {"order_id": order_id, "status": "created"}

    @Idempotent(expire=60)
    def generate_report(self, start_date: str, end_date: str):
        return {"report": "...", "generated_at": "..."}

注意事项:键必须包含真实业务唯一标识,不能只依赖对象字符串;缓存有大小限制,超出自动清理最旧条目;方法抛出异常时幂等键被移除允许重试;首次调用正在处理时后续请求会重新执行(简单实现)。

@AuditLog - 审计日志

参数

参数 类型 默认值 说明
action str "" 操作名称,如"创建用户"
target str "" 操作对象,如"用户管理"
detail str "" 操作详情,支持占位符,如"删除用户{user_id}"
level str "INFO" 日志级别:DEBUG/INFO/WARN/ERROR
from spring.annotations import AuditLog, Service

@Service
class UserService:
    @AuditLog(action="创建用户", target="用户管理", detail="创建用户{username}", level="INFO")
    def create_user(self, username: str, email: str):
        return {"user_id": 1, "username": username}

注意事项:日志在方法执行完成后(finally 块)记录;detail 支持 {参数名} 占位符动态填充;异常时状态标记为 FAILED,正常执行为 SUCCESS。只写应用日志,不等于不可篡改审计系统。

@FeatureToggle - 功能开关

参数name(str,必填,功能名称,环境变量为 FEATURE_{NAME})、default(bool,默认 False)

from spring.annotations import FeatureToggle, Service

@Service
class FeatureService:
    @FeatureToggle(name="new_payment", default=False)
    def new_payment_flow(self, order_id: str):
        return {"status": "new_flow"}

控制功能开关

from spring.aop.comprehensive_aop import enable_feature, disable_feature

enable_feature("new_payment")
disable_feature("new_payment")

注意事项:通过环境变量 FEATURE_{名称大写} 控制(true/1/yes/enabled 不区分大小写);功能未启用时抛出 Exception: Feature 'xxx' is not enabled

@Lock - 分布式锁

参数

参数 类型 默认值 说明
key str None 锁键,支持 {参数名} 动态拼接
expire int 10 锁过期时间(秒)
wait_timeout int 5 等待锁的超时时间(秒)
prefix str "lock" 锁键前缀
from spring.annotations import Lock, Service

@Service
class StockService:
    @Lock(key="product_{product_id}", wait_timeout=3, prefix="stock")
    def deduct_stock(self, product_id: str, quantity: int):
        return {"product_id": product_id, "remaining": 100}

注意事项:锁获取失败抛出 Exception: Could not acquire lock for ...;key 支持动态参数(前缀_{参数名});方法执行完成后自动释放锁。Redis 可用时是分布式锁,否则只是当前进程分段锁。

@Metrics - 指标监控

参数name(str,默认 None,指标名默认方法全限定名)、tags(List[str],默认 None,预留扩展)

收集的指标:count(调用总次数)、total_time(总耗时)、errors(错误次数)、min_time(最小耗时)、max_time(最大耗时)。

from spring.annotations import Metrics, Service

@Service
class OrderService:
    @Metrics(name="order.create")
    def create_order(self, user_id: str, product_id: str):
        return {"order_id": "ORD_123"}

获取指标数据

from spring.aop.comprehensive_aop import get_metrics

metrics = get_metrics()

注意事项:每 100 次调用自动打印一次统计日志;指标存储有大小限制,超出自动清理;线程安全。tags 当前未进入指标数据。

@Synchronized - 方法同步

参数lock_name(str,默认 None,默认使用方法全限定名)

from spring.annotations import Synchronized, Service

@Service
class CounterService:
    def __init__(self):
        self.count = 0

    @Synchronized
    def increment(self):
        self.count += 1
        return self.count

    @Synchronized(lock_name="counter_lock")
    def decrement(self):
        self.count -= 1
        return self.count

注意事项:比 @Lock 更轻量;相同 lock_name 的方法共享同一把锁;只使用本地锁,不是分布式锁;当前实现不可重入,注意避免死锁。

@Validate - 参数校验

参数

参数 类型 默认值 说明
field str None 要校验的参数名,不指定则校验所有参数
min_length int None 最小长度
max_length int None 最大长度
min float None 最小值(数值类型)
max float None 最大值(数值类型)
regex str None 正则表达式
message str None 自定义错误消息
from spring.annotations import Validate, Service

@Service
class UserService:
    @Validate(field="username", min_length=3, max_length=20)
    @Validate(field="age", min=1, max=120)
    @Validate(field="email", regex=r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$')
    def register(self, username: str, age: int, email: str):
        return {"status": "success"}

注意事项:可以在一个方法上使用多个 @Validate;数值校验会自动尝试转换为 float,非数值参数跳过;校验失败抛出 Exception: Validation failed: ...。抛普通异常,复杂 API 校验优先使用 FastAPI/Pydantic。

@Trace - 分布式追踪

参数trace_id_key(str,默认 "X-Trace-ID")、span_name(str,默认 None,默认使用方法名)

from spring.annotations import Trace, Service

@Service
class OrderService:
    @Trace(span_name="create_order")
    def create_order(self, user_id: str, product_id: str):
        return {"order_id": "ORD_123"}

注意事项:同一线程内的嵌套调用共享同一个 trace_id;trace_id 基于时间戳和线程 ID 生成;异常时记录错误日志。当前不从 HTTP Header 读取,也不向下游传播,不能替代 OpenTelemetry。

5.9 事务、缓存、任务与异步注解

@Transactional

参数propagation(str,默认 "REQUIRED")、rollback_for(List[Type[Exception]],默认 [])、no_rollback_for(List[Type[Exception]],默认 [])

from spring.annotations import Service, Transactional

@Service
class OrderService:
    @Transactional(rollback_for=[Exception])
    def create_order(self, user_id: int, product_id: int):
        # 任意一步异常都会回滚
        return {"order_id": 1}

边界:受管 Bean 执行;同步/异步方法支持 REQUIREDREQUIRES_NEWNESTEDSUPPORTSMANDATORYNOT_SUPPORTEDNEVER,且必须启用内嵌 MyBatis。详细语义见第 9 章事务。

@Cacheable

参数value(str,必填,缓存名称)、key(str,默认 None)、condition(str,默认 None)

from spring.annotations import Service, Cacheable

@Service
class UserService:
    @Cacheable(value="users", key="#user_id")
    def get_user(self, user_id: int):
        return {"id": user_id, "name": "test"}

边界:受管 Bean 执行;支持同步/异步返回值,本地内存缓存默认 TTL 300 秒;key 支持参数名和 {参数名} 模板,condition 支持参数名、!参数名 或 callable。缓存不跨进程。

@Retryable

参数:异常类型(value)、总尝试次数(max_retries)、Backoff、排除类型(exclude)、恢复方法(recover

from spring.annotations import Retryable
from spring.retry.retry_annotations import Backoff

@Retryable(
    value=(ConnectionError,),
    max_retries=3,
    backoff=Backoff(delay=1000, multiplier=2.0),
)
def call_remote(self):
    ...

边界max_retries=3 表示最多调用三次,包含首次调用(不是"首次调用后再重试三次");旧名称 max_attempts=3 仍兼容,但新代码统一使用 max_retries,同时传两个名称且值不同时会报错。backoff 可传 Backoff(...),也可直接传毫秒数(backoff=500 表示固定等待 500 毫秒)。同步方法使用阻塞等待,异步方法使用 asyncio.sleep()。全部失败后若设置 recover="recover_method",容器调用同一 Bean 上的恢复方法,否则重新抛出最后一个异常。只对幂等操作开启自动重试,数据库写入、支付和消息发送必须先设计幂等键或去重机制。

@Async

含义:在线程池或事件循环中异步调度方法。

from spring.annotations import Service, Async

@Service
class EmailService:
    @Async
    def send_email(self, to: str, content: str):
        time.sleep(1)  # 模拟发送耗时
        print(f"Email sent to {to}")

边界:同步方法提交到全局线程池并返回 concurrent.futures.Future;协程在已有 asyncio 事件循环中创建 Task,没有运行中事件循环时在线程池中运行 asyncio.run() 并返回 Future/Task。调用方必须 await.result() 才能接收结果和异常。线程池任务不会继承调用线程的 MyBatis 事务。

@Scheduled

参数fixed_rate(int,默认 None)、fixed_delay(int,默认 None)、cron(str,默认 None)、initial_delay(int,默认 0)

from spring.annotations import Service, Scheduled

@Service
class ScheduledTasks:
    @Scheduled(fixed_rate=5000)   # 每 5 秒执行一次
    def report_current_time(self):
        print("Current time:", time.time())

    @Scheduled(cron="0 * * * * *")  # 每分钟执行一次
    def hourly_task(self):
        print("Hourly task executed")

边界:容器启动时实际注册;多 worker/多副本会重复执行。生产环境应使用分布式锁或独立调度服务确保单次执行。

@AsyncResult

参数value。当前仅元数据,不是 Future/Task 类型。

5.10 安全、Cloud 与消息注解

安全注解必须放在容器创建的 Bean 上。自己 Controller()Service() 创建的对象不会经过 BeanFactory 安全切面。

注解/类型 设计意图 当前真实状态
@Authenticate 校验 JWT 并建立安全上下文 受管 Bean 实际执行;HTTP 控制器自动读取 Authorization: Bearer ...,普通 Bean 调用可传 token=;调用结束恢复原安全上下文
@PreAuthorize 按角色/权限表达式授权 受管 Bean 实际执行;未认证返回 401,权限不足返回 403
@Secured 按任一角色授权 受管 Bean 实际执行;角色来自 JWT 的 roles claim
@EnableDiscoveryClient 启用服务注册发现 仅元数据;需要显式初始化 Nacos/发现客户端
@NacosValue 读取并动态刷新 Nacos 配置 仅元数据;不会像 @Value 一样被当前配置注入器读取
@RefreshScope 配置变化时刷新 Bean 已接入容器刷新机制;复杂配置刷新和 Java proxy 语义不等价
@EnableFeignClients 扫描 Feign 接口 仅元数据;不会自动扫描注册
@FeignClient 创建远程 HTTP 客户端代理 仅元数据;需显式使用 spring.cloud.feign 中的客户端工厂;调用时自动传播 XID 和 trace 头
@SentinelResource 限流、业务异常 fallback 受管 Bean 方法会包装;已内嵌限流熔断引擎,无需 Sentinel Dashboard
@EnableGateway 启用 API Gateway 元数据标记;配合 GatewayRouter 使用,内嵌轻量 ASGI/WSGI 网关
@LoadBalanced @Bean 工厂返回对象添加负载均衡标记 @Bean 方法上会执行,但实际请求仍需配合框架负载均衡客户端
@GlobalTransactional 通过 Seata 管理全局事务 受管 Bean 方法调用 Seata manager;HTTP 模式为持久化补偿且要求幂等回调,强一致生产场景使用 distributed;不支持嵌套
@Valid 非空/嵌套对象基础检查 受管 Bean 方法会执行简化校验,不等同 Jakarta Bean Validation
@Validated 分组校验 会执行简化检查,但 groups 当前未驱动真正的分组规则
@RabbitListener 注册 RabbitMQ 消费者 可直接装饰受管 Bean 方法;容器声明队列/交换机、注册回调,并在刷新后启动后台消费;支持同步和异步回调
RabbitTemplate 主动发送 RabbitMQ 消息 它是普通类,不是注解;显式实例化后调用 send()

Cloud 注解(@EnableDiscoveryClient / @NacosValue / @RefreshScope / @EnableFeignClients / @FeignClient / @SentinelResource / @EnableGateway / @LoadBalanced / @GlobalTransactional)

Cloud 注解的参数、示例与边界已分离至独立文档:CLOUD_MODULE.md(§一 注解参考)。

@Valid / @Validated

参数groups(List[Type],默认 [])

@Valid 校验规则:空字符串不能为 "",嵌套对象递归检查属性不能为 None,实体类参数校验配合 @RequestBody 使用,嵌套实体校验时内部实体必须添加 @Valid@Validated 校验规则:数值类型不能小于 0、字符串 trim 后不能为空。

区别

特性 @Valid @Validated
分组校验 不支持 支持
嵌套校验 支持 不支持
使用位置 方法参数、字段 类、方法

边界groups 当前未驱动真正的分组规则,Java Bean Validation group 的完整语义目前只保留为元数据。@Valid 会把参数识别为 request body,实际字段校验由 FastAPI/Pydantic 的模型和约束完成。

@RabbitListener

from spring.annotations import Component, RabbitListener


@Component
class OrderConsumer:
    @RabbitListener(
        queue="order.created",
        exchange="orders",
        routing_key="order.created",
        auto_ack=False,
        prefetch_count=8,
    )
    async def handle(self, message: dict):
        await process_order(message)

边界:启用 RabbitMQ 后,容器会声明队列、可选声明并绑定交换机、按 prefetch_count 注册消费者,并在容器刷新后启动后台消费。回调正常结束后手动 ack,异常时 nack 并重新入队;auto_ack=True 则由客户端自动确认。RabbitTemplate 是显式发送类。

5.11 / 5.12 MyBatis 集成注解 与 DDL 自动建表注解

@MapperScan / @Mapper / @Select / @Insert / @Update / @Delete / @ResultMap / @Options / Param / @MapperTransactional(5.11)与 @entity / Index(5.12)已分离至独立文档:ORM_MODULE.md(§一 注解参考)。

5.13 注解组合使用与执行顺序

常用组合模式

# 接口防护三件套
@SentinelResource(value="xxx", fallback="xxx_fallback")  # 降级熔断
@Metrics(name="xxx")  # 性能监控
@RateLimit(max_requests=100, time_window=60)  # 限流
def xxx_method(self):
    pass
# 写操作安全组合
@GlobalTransactional  # 分布式事务
@Synchronized(lock_name="xxx_lock")  # 同步锁
@AuditLog(action="xxx", target="xxx")  # 审计日志
def xxx_write_method(self):
    pass
# 查询接口组合
@Idempotent(key="xxx_id", expire=300)  # 幂等缓存
@Metrics(name="xxx.query")  # 监控
@Trace(span_name="xxx_query")  # 追踪
def xxx_query_method(self):
    pass

注解执行顺序(AOP 从外到内):

1. @SentinelResource / @CircuitBreaker  (最外层,熔断降级)
2. @RateLimit                           (限流)
3. @Lock / @Synchronized                (锁)
4. @Metrics                             (监控)
5. @Trace                               (追踪)
6. @AuditLog                            (审计)
7. @Idempotent                          (幂等)
8. @Validate / @Valid / @Validated      (参数校验)
9. 业务方法

性能影响

注解 性能损耗 内存占用 线程安全
@RateLimit 低 (<1ms) ✓ 安全
@CircuitBreaker 低 (<1ms) ✓ 安全
@Idempotent 低 (<2ms) ✓ 安全
@AuditLog 极低 (<0.1ms) ✓ 安全
@FeatureToggle 极低 (<0.1ms) ✓ 安全
@Lock 中 (取决于锁竞争) ✓ 安全
@Metrics 低 (<0.5ms) ✓ 安全
@Synchronized 中 (取决于锁竞争) ✓ 安全
@Validate 低 (<1ms) ✓ 安全
@Trace 低 (<0.5ms) ✓ 安全
@SentinelResource 低 (<1ms) ✓ 安全
@GlobalTransactional 低 (<2ms) ✓ 安全

动态键可引用方法参数名。例如 key="order_{order_id}" 会根据调用参数生成键:

from spring.annotations import Idempotent, Lock, Metrics, Service, Validate


@Service
class PaymentService:
    @Metrics(name="payment.create")
    @Lock(key="payment_{order_id}", expire=10, wait_timeout=3)
    @Idempotent(key="payment_{order_id}", expire=300)
    @Validate(field="amount", min=0.01, message="amount must be positive")
    def create(self, order_id: str, amount: float):
        return {"order_id": order_id, "amount": amount}

这组注解的排列会影响包装顺序和异常可见范围。业务关键方法应测试重复请求、并发、Redis 中断、超时和异常五种路径,不要只测试一次正常调用。


6. IoC 与依赖注入

6.1 组件类型

注解 用途
@Component 通用组件
@Service 业务服务
@Repository 数据访问封装
@RestController / @Controller Web 控制器
@Configuration Bean 配置类
@Bean 工厂方法产生 Bean
@Primary 同类型多个 Bean 时的首选 Bean
@Profile 按激活环境筛选
@Lazy 延迟创建,直到首次被 get_bean()、注入、控制器或任务使用

6.2 构造器注入

from spring.annotations import Autowired, Service


@Service
class GreetingService:
    def greet(self, name: str) -> str:
        return f"Hello, {name}"


@Service
class UserService:
    @Autowired
    def __init__(self, greeting_service: GreetingService):
        self.greeting_service = greeting_service

依赖参数应写类型注解。构造器注入能在启动阶段暴露缺失和循环依赖,优先于字段注入。Bean 名默认由类名转换为小写下划线形式(如 UserMapper -> user_mapper)。

6.3 多实现与 @Qualifier

同类型存在多个 Bean 时,应使用 @Primary@Qualifier 指定名称。

6.4 配置类和 Bean

from spring.annotations import Bean, Configuration


@Configuration
class AppConfig:
    @Bean(name="clock")
    def clock(self):
        import time
        return time.time

@Bean 支持 namescopeinit_methoddestroy_method。生产资源应确保销毁方法可重复调用。

6.5 配置值

@Value 支持通过默认参数或字段注解注入配置。对一组配置优先使用 @ConfigurationProperties(prefix="..."),并为字段提供明确类型和默认值。

6.6 生命周期

from spring.annotations import Component, PostConstruct, PreDestroy


@Component
class ResourceHolder:
    @PostConstruct
    def start(self):
        pass

    @PreDestroy
    def stop(self):
        pass

应用关闭时会销毁容器资源;ASGI 关闭事件还会关闭 MyBatis SqlSessionFactory 和共享连接池。


7. Web 控制器

7.1 类和方法映射

from spring.annotations import (
    DeleteMapping, GetMapping, PatchMapping, PostMapping, PutMapping,
    RequestMapping, RestController,
)


@RequestMapping("/users")
@RestController
class UserController:
    @GetMapping("/{user_id}")
    def get(self, user_id: int):
        return {"id": user_id}

    @PostMapping("")
    def create(self, body: dict):
        return body

    @PutMapping("/{user_id}")
    def update(self, user_id: int, body: dict):
        return {"id": user_id, **body}

    @PatchMapping("/{user_id}")
    def patch(self, user_id: int, body: dict):
        return {"id": user_id, **body, "partial": True}

    @DeleteMapping("/{user_id}")
    def delete(self, user_id: int):
        return {"deleted": user_id}

未指定映射路径时,默认使用方法名;类级路径前缀必须使用 @RequestMapping("/users")

7.2 统一返回值

普通返回值会包装为 Result.success(data=...)。也可以显式返回:

from spring.web import Result

return Result.success({"id": 1}, message="created")
return Result.bad_request("name is required")
return Result.not_found("user not found")

Result.code 会成为真实 HTTP 状态码,不只是响应体字段。

7.3 全局异常处理

from spring.annotations import ControllerAdvice, ExceptionHandler
from spring.web import Result


@ControllerAdvice
class GlobalExceptionHandler:
    @ExceptionHandler(ValueError)
    def handle_value_error(self, error: ValueError):
        return Result.bad_request(str(error))

未处理异常对客户端返回通用 500,不暴露内部堆栈;详细信息写入服务日志。

7.4 CORS

server:
  cors:
    allow_origins:
      - https://console.example.com
    allow_credentials: true

不要在 allow_credentials: true 时使用 *。默认来源列表为空,保持同源策略。

7.5 拦截器

from spring.annotations import Component
from spring.web.interceptor import HandlerInterceptor


@Component
class AuditInterceptor(HandlerInterceptor):
    async def pre_handle(self, request, handler):
        request.state.started = True
        return True

    def after_completion(self, request, response, handler, exception=None):
        # 记录状态、耗时或异常
        pass

拦截器自动接入 FastAPI 请求生命周期;支持同步/异步 pre_handlepost_handleafter_completion/api/** 路径规则。需要显式路径范围时,将 InterceptorRegistry 传给 WebApplicationContext,并使用 include_path_patterns('/api/**') / exclude_path_patterns('/api/public/**')pre_handle 返回 False 时请求以 403 结束。


8. 内嵌 PyMyBatis ORM 与 DDL

本节(与 MyBatis 一致性、数据库配置、Mapper 注解、Mapper 扫描、Session、XML Mapper、分页、SQL 安全、DDL 自动建表、XML 功能矩阵)已分离至独立文档:ORM_MODULE.md(§二 功能说明)。

9. 事务

9.1 Service 事务

from spring.annotations import Autowired, Service, Transactional


@Service
class RegistrationService:
    @Autowired
    def __init__(self, user_mapper: UserMapper, audit_mapper: AuditMapper):
        self.user_mapper = user_mapper
        self.audit_mapper = audit_mapper

    @Transactional(rollback_for=[Exception])
    def register(self, name: str, email: str):
        user_id = self.user_mapper.insert(name, email)
        self.audit_mapper.insert("USER_CREATED", user_id)
        return user_id

执行语义:

  1. 进入方法时创建 Session 并开始事务。
  2. 当前上下文内所有受管 Mapper 共用该 Session。
  3. 正常返回时提交。
  4. 满足回滚规则的异常导致回滚。
  5. Session 在退出后归还连接池。

9.2 回滚规则

rollback_for 指定需要回滚的异常类型,no_rollback_for 指定不回滚类型。若异常被设为不回滚,事务先提交,再把原异常继续抛给上层。

9.3 传播级别

当前支持:

@Transactional(propagation="REQUIRED")
@Transactional(propagation="NESTED")

NESTED 在已有事务中创建 savepoint;没有外层事务时等价于启动一个物理事务。REQUIRES_NEW 会挂起外层事务并使用独立 Session/连接;NOT_SUPPORTED 会挂起外层事务并以自动提交方式执行;MANDATORY 在没有外层事务时抛出错误;NEVER 在存在外层事务时抛出错误。使用 REQUIRES_NEWNOT_SUPPORTED 时,连接池 max_size 至少应能容纳并发的外层和内层连接。

9.4 嵌套事务

同一 Session 的嵌套 REQUIRED 采用 rollback-only 语义:内层失败后,即使业务代码捕获内层异常,外层提交仍会失败并整体回滚。显式使用 NESTED 时,内层异常回滚到 savepoint;异常被外层捕获后,外层仍可继续写入并提交。NESTED 适合允许内层失败被捕获的场景。

9.5 手动事务

with factory.open_session() as session:
    with session.transaction():
        session.insert("INSERT INTO users(name) VALUES (#{name})", {"name": "A"})
        session.insert("INSERT INTO audit(event) VALUES (#{event})", {"event": "created"})

也可显式写出传播参数:

with session.transaction(
    isolation_level="READ_COMMITTED",
    propagation="REQUIRED",
):
    ...

SqlSession.transaction()@Transactional 支持全部七种传播模式。省略 propagation 等价于 REQUIRED;普通写操作不在显式事务中时会自动提交。写入成功会按语句 flushCache 配置使查询缓存失效,失败会回滚。


10. 安全与权限

10.1 JWT 初始化

jwt:
  secret_key: ${JWT_SECRET_KEY}
  algorithm: HS256
  expires_in: 3600
  issuer: springpy-api
  audience: springpy-client
  leeway: 5

允许算法为 HS256HS384HS512。生产密钥至少 32 字符并从密钥管理系统注入。

10.2 access/refresh token

from spring.security.jwt_utils import JwtUtils, jwt_utils

access = jwt_utils.generate_token({"sub": "user-1"})
refresh = jwt_utils.generate_refresh_token({"sub": "user-1"})
claims = jwt_utils.decode_token(access)
new_access = jwt_utils.refresh_token(refresh)
verified_claims = jwt_utils.verify_token(access)

# 类调用委托给同一个全局实例,适合只使用应用统一 JWT 配置时调用。
another_access = JwtUtils.generate_token({"sub": "user-2"})

# 显式实例拥有独立密钥和算法,适合租户隔离或测试。
tenant_jwt = JwtUtils(secret_key="at-least-32-characters-for-tenant-a")
tenant_access = tenant_jwt.generate_token({"sub": "tenant-user"})

常用 API 易错点

  • JwtUtils.generate_token(...) 类调用使用已由应用配置初始化的全局实例;JwtUtils(...) 实例调用使用该实例自己的密钥。
  • access token 不能当作 refresh token 使用,token 类型会被校验。
  • verify_token() 验证并返回 payload,适合直接读取 verified_claims["sub"]decode_token() 语义相同。两者对过期或无效 token 抛出异常;只需要真假结果时使用 validate_token()
  • 不同密钥生成的 token 不能交叉校验,不要混用不同实例生成和校验的 token。

10.3 方法权限注解

@Authenticate@PreAuthorize@Secured 已接入 BeanFactory 和 Web 上下文。@Authenticate 从 HTTP Authorization: Bearer <token> 建立当前调用的安全上下文;@PreAuthorize 支持 hasRole(...)hasAnyRole(...)hasPermission(...)hasAnyPermission(...)authentication.name == '...'@Secured 接受一个或多个角色。认证失败映射为 HTTP 401,授权失败映射为 403。

from spring.annotations import Authenticate, GetMapping, PreAuthorize, RequestMapping, RestController


@RestController
@RequestMapping("/admin")
class AdminController:
    @GetMapping("/report")
    @Authenticate
    @PreAuthorize("hasRole('ROLE_ADMIN')")
    def report(self):
        return {"scope": "admin"}

普通受管 Bean 方法也可通过 method(token=access_token) 认证。安全上下文基于 ContextVar,每次调用结束后恢复,避免并发请求互相污染。仍必须验证:安全上下文如何从 HTTP 请求建立;缺失、过期和伪造 token 的状态码;角色与资源级权限边界;异步调用是否传播用户上下文。

10.4 密码

密码哈希使用 bcrypt,不保存或记录明文密码。JWT 密钥加密签名 token,不用于保存用户密码。

10.5 安全基线

  • 生产环境设置 SPRING_PROFILES_ACTIVE=productionSTARTUP_FAIL_FAST=true
  • JWT_SECRET_KEY 使用至少 32 字符的随机密钥;生产环境会拒绝默认弱密钥。
  • CORS_ALLOW_CREDENTIALS=true 时不能使用 * 来源。
  • SQL 值始终使用 #{name} 参数绑定;${name} 默认禁用。
  • 数据库账号按最小权限配置,运行账号不要拥有 DDL 权限。
  • TLS 在可信网关或反向代理终止,并配置请求大小、超时和访问日志脱敏。
  • HTTP 路由还应对缺失、过期、伪造 token 以及角色越权编写集成测试。

11. 缓存、任务与高级 AOP

11.1 @Cacheable

当前 @Cacheable 使用 BeanFactory 内的本地缓存,默认最多 1000 项、TTL 300 秒。value 是缓存命名空间;key="user_id" 取同名参数,key="user_{user_id}" 使用模板,其他字符串作为固定键;condition="enabled"condition="!skip_cache" 或 callable 决定是否缓存。同步方法缓存普通返回值,异步方法会先 await 再缓存最终结果,不会缓存 coroutine。缓存不跨进程,也没有对应的自动驱逐注解。写操作后的业务缓存失效不由 ORM 查询缓存自动替代。

11.2 @Retryable

from spring.annotations import Retryable
from spring.retry.retry_annotations import Backoff

@Retryable(
    value=(ConnectionError,),
    max_retries=3,
    backoff=Backoff(delay=1000, multiplier=2.0),
)
def call_remote(self):
    ...

max_retries=3 表示最多调用三次,包含首次调用。每次重试按 delaymultipliermax_delayrandom_factor 计算退避。同步方法使用阻塞等待,异步方法使用 asyncio.sleep(),不会阻塞事件循环。全部失败后若设置 recover="recover_method",容器调用同一 Bean 上的恢复方法,否则重新抛出最后一个异常。只对幂等操作开启自动重试。

11.3 @Async

@Async 始终异步调度:同步方法提交到全局线程池;协程在已有 asyncio 事件循环中创建 Task,没有运行中事件循环时在线程池中运行 asyncio.run()。前者返回 asyncio.Task/包装 Future,普通同步调用返回 concurrent.futures.Future,调用方必须 await.result() 才能接收结果和异常。线程池任务不会继承调用线程的 MyBatis 事务,不要把它当成事务内的并行执行。

11.4 @Scheduled

from spring.annotations import Scheduled, Service


@Service
class CleanupJob:
    @Scheduled(cron="0 */5 * * * *")
    def cleanup(self):
        pass

多 worker 或多副本会重复注册任务。生产环境应使用分布式锁或独立调度服务确保单次执行。

11.5 高级 AOP 上线前验证

注解 用途 上线前验证
@RateLimit 限流 多进程/多副本一致性、Redis 故障
@CircuitBreaker 熔断 状态存储、半开恢复、超时
@Idempotent 幂等 键设计、TTL、并发竞争
@AuditLog 审计 脱敏、不可抵赖、存储失败
@Lock 分布式锁 租约续期、误释放、时钟
@Metrics 指标 标签基数、抓取和资源开销
@Validate 校验 嵌套对象和错误映射

11.6 云和消息组件

@SentinelResource@GlobalTransactional 和方法级 @LoadBalanced 有 AOP 消费路径;@EnableDiscoveryClient@FeignClient 等当前主要是元数据,Nacos 实际初始化由 discovery.enabledApplicationContext 启动流程控制。Nacos 客户端需要 nacos-sdk-pythonNACOS_SERVERNACOS_USERNAMENACOS_PASSWORD;Nacos 2.2+ Docker 服务端还需要 Base64 token 和 identity 环境变量。

配置 rabbitmq.enabled: true 并提供 host、port、username、password、virtual_host。开发环境也应在真实 Nacos、RabbitMQ、Redis 等环境执行集成、断线和重复投递测试。HTTP 事务模式会将协调元数据写入 seata.store_path,并在 worker 启动后周期恢复;它是补偿事务,不是 Seata AT,也不能单独满足支付、订单、库存的一致性要求。


12. SpringBootAI AI 模块

本节(新手入门、快速开始、配置、AI 注解、ChatClient 链式 API、Advisor、ETL、工具调用、自动装配、企业级能力、DeepSeek 全特性演示)已分离至独立文档:AI_MODULE.md。安装:pip install springbootAI[ai]

13. Java 迁移指南

本文说明如何把现有的 Java Spring Boot、Spring Cloud Alibaba 和 MyBatis 分层代码迁移到 SpringBootAI。目标是保留清晰的 Controller / Service / Mapper 边界、配置习惯和常用注解意图,而不是让 Python 运行 Java 代码。

13.1 迁移原则

  1. 先迁移接口契约和测试,再迁移框架注解。
  2. Python 使用类型标注、Pydantic 和显式依赖,比模拟 Java 反射更可靠。
  3. 只有由 ApplicationContext 创建的 Bean 才会获得事务、缓存、重试等 AOP 行为;手工 ClassName() 创建的对象不受容器管理。
  4. Java 中的 XML SQL 可以大部分保留,但数据库函数、分页、类型名和连接配置需要按目标 Python 驱动验证。
  5. 不把"有同名注解"理解为"与 Java 完全等价"。

13.2 项目结构对照

Java Spring Boot SpringBootAI
src/main/java/com/acme/Application.java acme/Application.py
src/main/resources/application.yml acme/application.ymlacme/config/application.yml
controller/ acme/controller/
service/ acme/service/
mapper/resources/mapper/ acme/mappers/ 和同目录/配置指定的 XML
@SpringBootTest unittest / pytest + SQLite 或真实数据库集成环境
mvn spring-boot:run python -m acme.Applicationuvicorn asgi:app

每一个 Python 包目录都需要 __init__.pyscan_base_packages@MapperScan 接受的是可导入包名,例如 acme.service,不是文件系统路径。

13.3 启动和依赖注入

启动类

Java:

@SpringBootApplication(scanBasePackages = "com.acme")
public class Application {
  public static void main(String[] args) {
    SpringApplication.run(Application.class, args);
  }
}

Python:

from spring.annotations import SpringBootApplication
from spring.main import run


@SpringBootApplication(scan_base_packages=["acme"])
class Application:
    pass


if __name__ == "__main__":
    run(Application)

Bean 注解映射

Java 注解 SpringBootAI 写法 行为和边界
@Component @Component 受管单例 Bean
@Service @Service 受管业务 Bean
@Repository @Repository 受管数据访问 Bean;它不同于 MyBatis 的 @Mapper
@RestController @RestController 注册 FastAPI JSON 路由
@Controller @Controller 当前仍按 API 响应处理,不提供 Java MVC 模板视图语义
@Configuration + @Bean 同名注解 支持工厂方法、scope 和生命周期回调
@Primary @Primary 多候选 Bean 的默认注入目标
@Qualifier("name") @Qualifier("name") 作为构造方法元数据使用;复杂逐参数歧义应拆分依赖
@Profile @Profile 筛选 Bean,不自动合并 application-{profile}.yml
@Lazy @Lazy 首次需要 Bean 时才创建

推荐构造器注入,并用 Python 类型标注表达依赖:

from spring.annotations import Autowired, Service
from acme.mappers.UserMapper import UserMapper


@Service
class UserService:
    @Autowired
    def __init__(self, user_mapper: UserMapper):
        self.user_mapper = user_mapper

配置:Java @Value("${client.timeout}") 对应把 Value 放在参数默认值;@ConfigurationProperties(prefix = "client") 对应放在组件类上(见第 5.5 节)。

13.4 Web 层迁移

Java Spring MVC SpringBootAI
@RequestMapping @RequestMapping,可标在类和方法上
@GetMapping / @PostMapping 同名注解
@PutMapping / @PatchMapping / @DeleteMapping 同名注解
@PathVariable 参数默认值 PathVariable("id")
@RequestParam 参数默认值 RequestParam("page", required=False, default=1)
@RequestBody 参数默认值 RequestBody()
@RequestHeader / @CookieValue 同名参数标记
@ControllerAdvice / @ExceptionHandler 同名注解
@ResponseStatus 同名注解
HandlerInterceptor 继承 HandlerInterceptor 并标记 @Component
from pydantic import BaseModel
from spring.annotations import (
    GetMapping, PathVariable, PostMapping, RequestBody, RequestMapping,
    RestController, Valid,
)


class CreateUserRequest(BaseModel):
    name: str
    email: str


@RequestMapping("/users")
@RestController
class UserController:
    @GetMapping("/{user_id}")
    def get_one(self, user_id: int = PathVariable("user_id")):
        return {"id": user_id}

    @PostMapping("")
    def create(self, body: CreateUserRequest = Valid()):
        return {"name": body.name, "email": body.email}

@Valid@Validated 会把该参数识别为 request body;实际字段校验由 FastAPI/Pydantic 的模型和约束完成。Java Bean Validation group 的完整语义目前只保留为元数据,不应依赖它做分组校验。

13.5 AOP、任务和本地事务

Java 能力 SpringBootAI 注意事项
@Transactional @Transactional 支持 REQUIREDREQUIRES_NEWNESTEDSUPPORTSMANDATORYNOT_SUPPORTEDNEVERREQUIRES_NEW 使用独立 Session/连接,连接池必须能同时提供外层和内层连接
@Cacheable @Cacheable 本地缓存默认 TTL 300 秒;Redis 后端需要额外部署
Spring Retry @Retryable @Retryable max_retries 包含首次调用,只应用于幂等操作
@Async @Async 返回 Future / Task;不会继承调用线程的数据库事务
@Scheduled @Scheduled 每个 worker 都会调度,分布式部署需自行选主或加锁
@PostConstruct / @PreDestroy 同名注解 依赖正常容器启动和关闭

NESTED 适合允许内层失败被捕获的场景:内层会回滚到 savepoint,外层仍可提交。普通嵌套 REQUIRED 保持 Java 常见的 rollback-only 语义,内层失败即使被业务代码捕获,外层提交也会失败。

13.6 MyBatis 到 PyMyBatis

Mapper 注解

Java:

@Mapper
public interface UserMapper {
  @Select("select id, name from users where id = #{id}")
  User findById(@Param("id") long id);

  @Options(useGeneratedKeys = true, keyProperty = "id")
  @Insert("insert into users(name) values(#{user.name})")
  int insert(@Param("user") User user);
}

Python:

from dataclasses import dataclass
from typing import Optional
from spring.orm import Insert, Mapper, Param, Select


@dataclass
class User:
    name: str
    id: Optional[int] = None


@Mapper
class UserMapper:
    @Select("SELECT id, name FROM users WHERE id = #{id}")
    def find_by_id(self, id: int) -> Optional[User]:
        pass

    @Insert(
        "INSERT INTO users(name) VALUES (#{user.name})",
        use_generated_keys=True,
        key_property="id",
    )
    def insert(self, user: User) -> int:
        pass

XML 功能矩阵见第 8.10 节(含 <resultMap><sql>+<include><if>/<where>/<set>/<trim><choose>/<when>/<otherwise><foreach><bind>resultTypefetchSize/timeout/useCache/flushCacheuseGeneratedKeys/keyProperty/keyColumn<association>/<collection><selectKey>databaseId、Provider,以及 Java plugin/executor 不兼容需使用 Python Interceptor)。

13.7 Spring Cloud Alibaba 对照

Java 注解/组件 SpringBootAI 对应 当前状态
@EnableDiscoveryClient + Nacos @EnableDiscoveryClient + discovery 配置 注解元数据与 Nacos 客户端配置可用;需部署 Nacos 并做注册/发现集成测试
@NacosValue / @RefreshScope 同名注解 元数据可用;@RefreshScope 已接入容器刷新机制,复杂配置刷新和 Java proxy 语义不等价
@EnableFeignClients / @FeignClient 同名注解 + spring.cloud.feign 主要用于客户端元数据和 HTTP 调用;不兼容 Java interface proxy。Feign 调用自动传播 XID 和 trace 头
@LoadBalanced 同名注解 使用 Python 负载均衡实现;不要复用 RestTemplate 用法
Sentinel @SentinelResource 同名注解 已内嵌限流熔断引擎,无需 Dashboard;如需更强大治理能力可对接外部 Sentinel Dashboard
Spring Cloud Gateway @EnableGateway + GatewayRouter 内嵌轻量 ASGI/WSGI 网关;复杂网关需求可使用 Kong/APISIX 等专业网关
Seata @GlobalTransactional 同名注解 http 模式是持久化补偿协调器,依赖幂等分支回调;企业强一致场景必须配置真实 Seata Server 与兼容 SDK

Cloud 高级功能迁移对照

Java Spring Cloud SpringBootAI 写法 说明
Sentinel Dashboard + @SentinelResource @SentinelResource 内嵌引擎,无需 Dashboard;支持 QPS 限流、异常比例/异常数/慢调用熔断、热点参数限流
SkyWalking Agent + OAP Server @Trace + 内嵌 Tracer 原生 OpenTelemetry(W3C traceparent),无需 OAP Server;自动注入 HTTP/Feign 追踪头
Seata Server + @GlobalTransactional @GlobalTransactional distributed 模式对接 Seata Server;http 仅用于补偿流程和故障演练,不提供 AT 语义
Spring Cloud Gateway GatewayRouter 轻量 ASGI/WSGI 网关,支持路由转发、路径重写、过滤器链、负载均衡
JPA hibernate.ddl-auto @entity + ddl-auto 配置 支持 create/update/validate/create-drop;自动扫描实体包,自动建表/添加列/创建索引

DDL Auto 迁移示例

Java JPA:

@Entity
@Table(name = "users")
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(nullable = false, unique = true)
    private String username;

    private String email;
}

SpringBootAI:

from spring.orm import entity, Index

@entity("users", indexes=[
    Index("idx_username", ["username"], unique=True),
])
class User:
    def __init__(self, id: int = None, username: str = "", email: str = ""):
        self.id = id
        self.username = username
        self.email = email

application.yml 配置:

database:
  ddl-auto:
    mode: update  # 对应 spring.jpa.hibernate.ddl-auto=update
    entity_packages: app.entity

13.8 配置迁移示例

spring:
  application:
    name: order-service

database:
  enabled: true
  orm: mybatis
  driver: sqlite
  database: ./order.db
  min_size: 1
  max_size: 10
  mapper_locations:
    - acme/mappers/*.xml
  security:
    block_ddl: true
    sql_injection_detection: true
    allow_raw_params: false

discovery:
  enabled: false

server:
  host: 127.0.0.1
  port: 8080

Java 的 profile 文件自动合并不是当前功能。部署流程应生成最终 application.yml,或显式设置配置路径。数据库 DDL 使用 Alembic、Flyway 或独立迁移任务;线上运行账户不应具有 DDL 权限。

13.9 验证顺序

  1. 创建本地环境:python -m venv .venv,然后 .venv/bin/python -m pip install -e ".[dev]"
  2. 运行内置契约测试:.venv/bin/python -m unittest discover -s tests -v
  3. 用 SQLite 验证 Mapper SQL、事务、动态 SQL 和类型映射。
  4. 用目标 MySQL/PostgreSQL/Oracle 版本执行相同测试,特别验证自增主键、事务隔离、超时和连接中断。
  5. 启动 ASGI 应用,检查 /docs/actuator/health/liveness/actuator/health/readiness
  6. 接入 Nacos、RabbitMQ、Redis 等外部中间件,并演练断线、重复投递和回滚。
  7. 验证 Cloud 功能:@SentinelResource 限流熔断、@Trace 追踪、@GlobalTransactional 补偿流程、GatewayRouter 网关、@entity + ddl-auto 自动建表。HTTP 补偿模式必须验证重复回调、进程重启和部分失败;强一致事务需部署真实 Seata Server 并执行集成测试。

14. 生产部署

14.1 环境要求

组件 版本要求 说明
Python 3.10+ 推荐 3.12
Redis 6.0+ 用于分布式锁、限流、缓存
MySQL 5.7+ / 8.0+ 用于业务数据存储
Nacos 2.0+ 服务注册发现(可选)

v1.5.0+ 新特性:内嵌 Sentinel 限流熔断、OpenTelemetry 分布式追踪和轻量异步 API Gateway。HTTP 补偿模式不提供 Seata AT 语义;生产分布式事务必须部署真实 Seata Server 并提供兼容适配器。

14.2 基础服务部署

Redis:

# Ubuntu/Debian
sudo apt update && sudo apt install redis-server
# CentOS/RHEL
sudo yum install redis
sudo systemctl start redis && sudo systemctl enable redis
redis-cli ping   # 应返回 PONG

配置文件 /etc/redis/redis.conf:设置密码 requirepass your_secure_password,绑定地址 bind 0.0.0.0(生产注意安全)。

MySQL:

sudo apt install mysql-server   # 或 yum install mysql-community-server
sudo systemctl start mysqld && sudo systemctl enable mysqld

MySQL 8+ 默认使用 caching_sha2_password 认证插件,若连接失败:

CREATE USER 'spring_python'@'%' IDENTIFIED BY 'your_secure_password';
GRANT ALL PRIVILEGES ON your_database.* TO 'spring_python'@'%';
FLUSH PRIVILEGES;
-- 需要 mysql_native_password(不推荐,但兼容性更好)
ALTER USER 'spring_python'@'%' IDENTIFIED WITH mysql_native_password BY 'your_secure_password';

JDBC URL 建议:

mysql+pymysql://spring_python:password@localhost:3306/your_database?charset=utf8mb4&allowPublicKeyRetrieval=true&useSSL=false

Nacos(可选):

wget https://github.com/alibaba/nacos/releases/download/2.3.0/nacos-server-2.3.0.tar.gz
tar -zxvf nacos-server-2.3.0.tar.gz && cd nacos/bin
./startup.sh -m standalone   # 控制台 http://localhost:8848/nacos 默认 nacos/nacos

Windows Docker Desktop 下 Nacos 2.2.x 在 Java 8 的 cgroup v2 环境可能因 ProcessorMetrics 报 NPE,启动容器时注入 JAVA_TOOL_OPTIONS=-XX:-UseContainerSupport。若使用 MySQL 外部存储,需设置 SPRING_DATASOURCE_PLATFORM=mysqlMYSQL_SERVICE_* 连接参数,并先将镜像内 /home/nacos/conf/mysql-schema.sql 导入目标 nacos 数据库。

14.3 Cloud 功能

已分离至独立文档:CLOUD_MODULE.md(§二 功能说明)。

14.4 生产配置文件

创建 application-prod.yml(可选):

server:
  port: 8080

redis:
  enabled: true
  host: your-redis-host
  port: 6379
  password: your-redis-password

jwt:
  secret_key: your-strong-secret-key-change-in-production
  expires_in: 7200

database:
  enabled: true
  url: mysql+pymysql://user:password@localhost:3306/your_database?charset=utf8mb4
  # DDL Auto 生产环境建议使用 validate 模式
  ddl-auto:
    mode: validate
    entity_packages: app.entity

discovery:
  enabled: true
  server_addr: nacos:8848
  username: ${NACOS_USERNAME}
  password: ${NACOS_PASSWORD}

logging:
  level: INFO
  log_dir: /var/log/spring-python

内嵌 Cloud 功能默认即可用,无需外部 Server,也不需要在 application-prod.yml 中额外配置。

生产环境变量速查:

环境变量 说明 默认值
SERVER_PORT 服务端口 8080
SYNC_MAX_WORKERS 每个 worker 的同步处理线程上限 40
SYNC_MAX_QUEUE 每个 worker 可等待的同步请求数 100
SYNC_QUEUE_TIMEOUT 同步队列等待秒数,超时返回 503 0.1
REDIS_HOST / REDIS_PORT / REDIS_PASSWORD Redis 地址/端口/密码 localhost/6379/空
JWT_SECRET_KEY JWT 密钥 spring-python-secret-key-change-in-production
DB_URL 数据库连接 URL sqlite:///./test.db
DB_DDL_AUTO DDL 自动建表模式(none/validate/update/create/create-drop) none
DB_ENTITY_PACKAGES 实体类包路径,逗号分隔
DISCOVERY_ENABLED 是否启用 Nacos 服务发现 false
NACOS_SERVER Nacos 地址 localhost:8848
NACOS_USERNAME / NACOS_PASSWORD Nacos 客户端账号/密码
SEATA_HTTP_STORE_PATH HTTP 补偿协调 SQLite 文件路径(同主机多 worker 共享) ./data/seata-http.sqlite3
SEATA_HTTP_RECOVER_ON_STARTUP 初始化时扫描并恢复未完成补偿 true
SEATA_HTTP_RECOVERY_GRACE_MS 接管其他 worker 的 COMMITTING/ROLLING_BACK 前等待时间 30000
SEATA_HTTP_RECOVERY_INTERVAL_S worker 内周期恢复间隔,0 表示关闭 30
SPRING_DISABLE_DOCKER_IP_DETECT 设为 1 禁用 Docker 容器 IP 自动检测 0

HTTP 补偿模式使用 SEATA_HTTP_* 配置,仍不提供 Seata AT;生产强一致事务必须配置 SEATA_MODE=distributed、真实 Server 和兼容 SDK。

14.5 启动应用

开发模式:

python -m spring.main

生产模式(ASGI + Uvicorn):

export SPRING_PROFILES_ACTIVE=production
export JWT_SECRET_KEY="使用密钥管理系统注入至少32字符的随机值"
export STARTUP_FAIL_FAST=true
# myapp/asgi.py: from spring import create_app; app = create_app(Application)
uvicorn myapp.asgi:app --host 0.0.0.0 --port 8080 --workers 4

使用 Gunicorn(推荐):

pip install gunicorn uvicorn
gunicorn -w 4 -k uvicorn.workers.UvicornWorker -b 0.0.0.0:8080 myapp.asgi:app

作为系统服务(systemd): 创建 /etc/systemd/system/spring-python.service

[Unit]
Description=Spring Python Application
After=network.target redis.service mysqld.service

[Service]
Type=simple
User=spring-python
WorkingDirectory=/opt/spring-python
Environment="SPRING_PROFILES_ACTIVE=production"
Environment="STARTUP_FAIL_FAST=true"
ExecStart=/usr/bin/python -m spring.main
Restart=always
RestartSec=5

[Install]
WantedBy=multi-user.target
sudo systemctl daemon-reload
sudo systemctl start spring-python
sudo systemctl enable spring-python

连接池容量: 每个 worker 有独立连接池。数据库最大连接需求近似 实例数 x worker 数 x database.max_size,还应给迁移、监控和运维连接预留容量。池耗尽时 wait_timeout 应快速失败并配合指标和告警。

优雅退出: ASGI shutdown 会关闭 MyBatis 工厂。仍需在部署平台设置足够终止宽限期,让在途请求、事务和消息确认完成。

14.6 验证部署

curl http://localhost:8080/actuator/health

响应示例:

{
    "status": "UP",
    "components": {
        "redis": "UP",
        "database": "UP",
        "nacos": "UP",
        "rabbitmq": "UP"
    }
}

Sentinel、OpenTelemetry 追踪和 API Gateway 可内嵌运行;HTTP 补偿协调器的未完成事务会纳入恢复日志。它不属于强一致外部事务协调器,不能替代 Seata Server。

14.7 部署故障排查

Nacos Docker 启动失败(退出码 255): 使用 Nacos 2.2+ 时配置 NACOS_AUTH_ENABLE=true、Base64 token(解码后至少 32 字节)以及 NACOS_AUTH_IDENTITY_KEY / NACOS_AUTH_IDENTITY_VALUE;Windows Docker 追加 JAVA_TOOL_OPTIONS=-XX:-UseContainerSupport 并映射 8848/9848 端口;外部 MySQL 先导入 schema。用 liveness/readiness 端点验证而非只看进程状态:

curl http://127.0.0.1:8848/nacos/v1/console/health/liveness
curl http://127.0.0.1:8848/nacos/v1/console/health/readiness

MySQL 认证问题(Access denied for user 'root'@'localhost'): 确认密码正确;MySQL 8+ 在 JDBC URL 添加 allowPublicKeyRetrieval=true;检查用户权限 SHOW GRANTS FOR 'user'@'%';;Docker 环境 localhost 认证失败时设置 SPRING_DISABLE_DOCKER_IP_DETECT=0 启用容器 IP 检测。

Redis 连接问题(ConnectionError: Error 111):redis-cli ping 检查服务;检查防火墙规则;检查绑定地址(bind 0.0.0.0)。

DDL Auto 建表失败: 确保数据库用户有 DDL 权限(CREATE/ALTER/DROP);生产环境使用 validate 而非 create/update;检查实体字段类型是否在支持范围内(int/str/float/bool/bytes/datetime)。


15. 项目结构

exampleexample1example5 是仓库级示例,不属于 springbootAI 安装包,不会被打包。实际项目应创建自己的应用包。

推荐目录结构:

myapp/
|-- __init__.py
|-- Application.py
|-- application.yml
|-- controller/
|   |-- __init__.py
|   `-- UserController.py
|-- service/
|   |-- __init__.py
|   `-- UserService.py
|-- mappers/
|   |-- __init__.py
|   `-- UserMapper.py
|-- config/
|   `-- AppConfig.py
`-- exception/
    `-- GlobalExceptionHandler.py

每个被扫描目录都应包含 __init__.py,并从项目根目录启动,确保包可导入。scan_base_packages@MapperScan 接受的是可导入包名(如 myapp.service),不是文件系统路径。

Java 项目结构对照(详见第 13 章):

Java Spring Boot SpringBootAI
src/main/java/com/acme/Application.java acme/Application.py
src/main/resources/application.yml acme/application.ymlacme/config/application.yml
controller/ / service/ acme/controller/ / acme/service/
mapper/resources/mapper/ acme/mappers/ 和同目录/配置指定的 XML
@SpringBootTest unittest / pytest + SQLite 或真实数据库集成环境
mvn spring-boot:run python -m acme.Applicationuvicorn asgi:app

16. 测试

16.1 运行测试

从工作区根目录:

python -m pytest -q tests

详细的测试环境、套件覆盖、功能矩阵、企业就绪评估与 example_all 集成测试结果,见 TEST_REPORT.md

16.2 重点覆盖

  • 独立和内嵌 ORM 源码一致。
  • 连接池共享、扩容、归还和未提交回滚。
  • 普通事务与嵌套 rollback-only。
  • Spring Mapper 在事务中复用 Session。
  • JWT access/refresh、生产密钥校验。
  • 配置占位符类型和 CORS/HTTP 错误状态。
  • AI 模块 87 用例(LangChain 切片委托 + 向量库适配器),全量 707 用例 0 失败。

17. 常见问题与排错

17.1 启动时找不到组件

  1. 目录是否有 __init__.py
  2. scan_base_packages 是否是可导入包名,不是文件路径。
  3. 启动工作目录是否包含项目根目录。
  4. 组件类是否带 @Service@RestController 等注解。
  5. @Profile 是否与当前环境一致。

17.2 Mapper 未注册

检查 database.enabled: truedatabase.orm: mybatis@Mapper@MapperScan 路径和 Mapper 模块导入错误。扫描失败会写 warning,应查看完整启动日志。

17.3 @Transactional 报缺少工厂

说明 MyBatis 没有初始化。确认数据库已启用、ORM 模式正确、配置有效,并且 Service 是由 Spring 容器创建而不是手工 UserService()

17.4 数据库连接耗尽

检查 Session 是否通过上下文管理器关闭、请求是否有长事务、查询是否阻塞,以及 实例 x worker x max_size 是否超过数据库上限。不要在全局变量中长期保存 SqlSession

17.5 生产启动拒绝 JWT

设置:

SPRING_PROFILES_ACTIVE=production
STARTUP_FAIL_FAST=true
JWT_SECRET_KEY=<至少32字符随机密钥>

不要把真实密钥提交到仓库。

17.6 Nacos、PATCH 和配置同步排错

Nacos Docker 退出码 255 且日志提示 NACOS_AUTH_TOKEN 确认服务端同时配置了 NACOS_AUTH_ENABLE=true、Base64 编码且解码后至少 32 字节的 NACOS_AUTH_TOKENNACOS_AUTH_IDENTITY_KEYNACOS_AUTH_IDENTITY_VALUE。Windows Docker 还应设置 JAVA_TOOL_OPTIONS=-XX:-UseContainerSupport,并把镜像中的 mysql-schema.sql 导入外部 Nacos 数据库。

PATCH /api/... 返回 404: 确认方法使用 @PatchMapping,并检查 Web 上下文日志中是否注册了 PATCH 路由;框架已将该注解接入 fastapi_app.patch(),不需要手工调用 add_api_route

ConfigLoader() 与上下文读取不同文件: 确认应用通过 ApplicationContext 启动,而不是只在不同工作目录直接实例化加载器。上下文启动后会绑定全局实例和默认配置目录;需要加载独立配置时显式传入 config_pathbase_path

17.7 上线前清单

  • 使用实际 MySQL/PostgreSQL/Oracle 版本运行 CRUD、事务、断连恢复和池耗尽测试。
  • 使用迁移工具管理结构,不让应用运行账号执行 DDL。
  • 锁定依赖并生成 SBOM,执行漏洞和许可证扫描。
  • 为 JWT、数据库、Redis、RabbitMQ 使用密钥管理系统。
  • 配置 TLS、CORS 白名单、请求限制和真实 HTTP 错误码监控。
  • 验证备份恢复、主从切换和慢 SQL 告警。
  • 对定时任务、多 worker 和多副本设计唯一执行或幂等。
  • 执行越权、SQL 注入、重放、日志泄露和依赖故障测试。
  • 验证优雅退出不会中断事务或丢失消息。

18. 性能与容量验证

仓库提供 Docker 化的 SpringBootAI 基准服务和 k6 smokebaselinestresssoak 四档压测。快速验证:

.\scripts\run-load-test.ps1 -Profile smoke

Bean Validation、缓存增强、CSV、JPA 乐观锁和 Conditional 均有独立 workload;条件装配另有重复 BeanDefinition 注册基准。完整参数、业务接口压测和真实 Seata 契约测试说明见 tests_performance/README.md

附录 A:完整环境变量清单

# Server
export SERVER_PORT=8080
export SERVER_HOST=0.0.0.0

# Redis
export REDIS_ENABLED=true
export REDIS_HOST=localhost
export REDIS_PORT=6379
export REDIS_PASSWORD=
export REDIS_DB=0
export REDIS_TIMEOUT=5000

# JWT
export JWT_SECRET_KEY=your-secret-key
export JWT_ALGORITHM=HS256
export JWT_EXPIRES_IN=3600

# Database
export DB_ENABLED=false
export DB_URL=sqlite:///./test.db
export DB_USERNAME=
export DB_PASSWORD=
export DB_DRIVER=sqlite
export DB_HOST=localhost
export DB_PORT=3306
export DB_DATABASE=./test.db

# ORM DDL Auto
export DB_DDL_AUTO=none  # none|validate|update|create|create-drop
export DB_ENTITY_PACKAGES=  # 实体类包路径,逗号分隔

# Nacos
export DISCOVERY_ENABLED=false
export NACOS_SERVER=localhost:8848
export NACOS_NAMESPACE=
export NACOS_GROUP=DEFAULT_GROUP
export NACOS_USERNAME=nacos
export NACOS_PASSWORD=nacos

# Nacos Docker server authentication (Nacos 2.2+)
export NACOS_AUTH_ENABLE=true
export NACOS_AUTH_TOKEN=<base64-token-with-at-least-32-decoded-bytes>
export NACOS_AUTH_IDENTITY_KEY=springpy
export NACOS_AUTH_IDENTITY_VALUE=springpy-local

# Docker 辅助
export SPRING_DISABLE_DOCKER_IP_DETECT=0  # 设为1禁用容器IP自动检测

# Retry
export RETRY_ENABLED=true
export RETRY_MAX_RETRIES=3
export RETRY_DELAY=1000
export RETRY_MAX_DELAY=10000
export RETRY_MULTIPLIER=2.0
export RETRY_RANDOM_FACTOR=0.1

# RabbitMQ
export RABBITMQ_ENABLED=false
export RABBITMQ_HOST=localhost
export RABBITMQ_PORT=5672
export RABBITMQ_USERNAME=guest
export RABBITMQ_PASSWORD=guest

# Prometheus
export PROMETHEUS_ENABLED=false
export PROMETHEUS_PORT=8000

# Logging
export LOG_LEVEL=INFO
export LOG_DIR=logs

Sentinel 限流熔断、OpenTelemetry 分布式追踪和 API Gateway 可内嵌实现;HTTP 补偿事务通过 SEATA_HTTP_* 配置。AI 模块环境变量见第 12.2 节。

附录 B:Docker Compose 示例

version: '3.8'

services:
  redis:
    image: redis:7-alpine
    ports:
      - "6379:6379"
    volumes:
      - redis_data:/data

  mysql:
    image: mysql:8.0
    ports:
      - "3306:3306"
    environment:
      MYSQL_ROOT_PASSWORD: root
      MYSQL_DATABASE: example_db
    volumes:
      - mysql_data:/var/lib/mysql

  nacos:
    image: nacos/nacos-server:v2.3.0
    ports:
      - "8848:8848"
      - "9848:9848"
    environment:
      MODE: standalone
      # Nacos 2.2+ requires a Base64-encoded token (at least 32 decoded bytes)
      NACOS_AUTH_ENABLE: "true"
      NACOS_AUTH_TOKEN: "c3ByaW5ncHktbmFjb3MtaGFuZHNoYWtlLXNlY3JldC0yMDI2LTA4LTA0LTAx"
      NACOS_AUTH_IDENTITY_KEY: "springpy"
      NACOS_AUTH_IDENTITY_VALUE: "springpy-local"
      JAVA_TOOL_OPTIONS: "-XX:-UseContainerSupport"

volumes:
  redis_data:
  mysql_data:

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

springbootai-1.8.2.tar.gz (577.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

springbootai-1.8.2-py3-none-any.whl (465.5 kB view details)

Uploaded Python 3

File details

Details for the file springbootai-1.8.2.tar.gz.

File metadata

  • Download URL: springbootai-1.8.2.tar.gz
  • Upload date:
  • Size: 577.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for springbootai-1.8.2.tar.gz
Algorithm Hash digest
SHA256 f562b09f4205741cbd672984888595ad2332aa4538e6918674ae8a6fa56298c3
MD5 2f3404df4017c86fe934a7792d77cee4
BLAKE2b-256 c370fdcd7e3afdb424db3fb01a439a807e1d6055ebafb8e8b3871892c3ea6e77

See more details on using hashes here.

Provenance

The following attestation bundles were made for springbootai-1.8.2.tar.gz:

Publisher: publish.yml on YUCONGGEN/springbootAI

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file springbootai-1.8.2-py3-none-any.whl.

File metadata

  • Download URL: springbootai-1.8.2-py3-none-any.whl
  • Upload date:
  • Size: 465.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for springbootai-1.8.2-py3-none-any.whl
Algorithm Hash digest
SHA256 859df4df43946af4339376f0232e40840bf5b4134e0f97d3a38d8a8d480c8ec4
MD5 b7cb313f25d0b577baf48b0f9749dde5
BLAKE2b-256 18992c7b125571693d27e082fa8a83f36cb11f4644860353110e16d3aa8740c6

See more details on using hashes here.

Provenance

The following attestation bundles were made for springbootai-1.8.2-py3-none-any.whl:

Publisher: publish.yml on YUCONGGEN/springbootAI

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page