springbootAI 2.3.4__tar.gz → 2.3.5__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (348) hide show
  1. {springbootai-2.3.4 → springbootai-2.3.5}/CHANGELOG.md +8 -0
  2. {springbootai-2.3.4/springbootAI.egg-info → springbootai-2.3.5}/PKG-INFO +39 -7
  3. {springbootai-2.3.4 → springbootai-2.3.5}/README.md +38 -6
  4. {springbootai-2.3.4 → springbootai-2.3.5}/pyproject.toml +1 -1
  5. {springbootai-2.3.4 → springbootai-2.3.5/springbootAI.egg-info}/PKG-INFO +39 -7
  6. {springbootai-2.3.4 → springbootai-2.3.5}/springbootAI.egg-info/SOURCES.txt +3 -0
  7. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/__init__.py +1 -1
  8. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/ai/__init__.py +1 -1
  9. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/annotations/__init__.py +10 -0
  10. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/annotations/conditional.py +112 -0
  11. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/annotations/core.py +24 -1
  12. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/aop/aspect.py +111 -2
  13. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/context/bean_factory.py +185 -11
  14. springbootai-2.3.5/springbootai/context/lifecycle.py +241 -0
  15. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/csv/__init__.py +1 -1
  16. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/data/__init__.py +1 -1
  17. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/datasource/__init__.py +1 -1
  18. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/excel/__init__.py +1 -1
  19. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/i18n/__init__.py +1 -1
  20. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/langchain/__init__.py +1 -1
  21. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/logging/loguru_logger.py +7 -1
  22. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/orm/pymybatis/__init__.py +1 -1
  23. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/orm/pymybatis/version.py +1 -1
  24. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/security/secret_manager.py +2 -2
  25. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/test/__init__.py +1 -1
  26. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/tx/__init__.py +1 -1
  27. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/utils/banner.py +2 -2
  28. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/validation/__init__.py +1 -1
  29. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/websocket/__init__.py +1 -1
  30. {springbootai-2.3.4 → springbootai-2.3.5}/tests/test_annotations_contract.py +1 -0
  31. springbootai-2.3.5/tests/test_aop_pointcut_enhancements.py +201 -0
  32. springbootai-2.3.5/tests/test_ioc_lifecycle_enhancements.py +328 -0
  33. {springbootai-2.3.4 → springbootai-2.3.5}/LICENSE +0 -0
  34. {springbootai-2.3.4 → springbootai-2.3.5}/MANIFEST.in +0 -0
  35. {springbootai-2.3.4 → springbootai-2.3.5}/SECURITY.md +0 -0
  36. {springbootai-2.3.4 → springbootai-2.3.5}/requirements-ai.txt +0 -0
  37. {springbootai-2.3.4 → springbootai-2.3.5}/requirements-langgraph.txt +0 -0
  38. {springbootai-2.3.4 → springbootai-2.3.5}/requirements-mcp.txt +0 -0
  39. {springbootai-2.3.4 → springbootai-2.3.5}/requirements.txt +0 -0
  40. {springbootai-2.3.4 → springbootai-2.3.5}/setup.cfg +0 -0
  41. {springbootai-2.3.4 → springbootai-2.3.5}/setup.py +0 -0
  42. {springbootai-2.3.4 → springbootai-2.3.5}/springbootAI.egg-info/dependency_links.txt +0 -0
  43. {springbootai-2.3.4 → springbootai-2.3.5}/springbootAI.egg-info/entry_points.txt +0 -0
  44. {springbootai-2.3.4 → springbootai-2.3.5}/springbootAI.egg-info/requires.txt +0 -0
  45. {springbootai-2.3.4 → springbootai-2.3.5}/springbootAI.egg-info/top_level.txt +0 -0
  46. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/ai/advisors.py +0 -0
  47. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/ai/annotation_runtime.py +0 -0
  48. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/ai/annotations.py +0 -0
  49. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/ai/autoconfig.py +0 -0
  50. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/ai/core.py +0 -0
  51. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/ai/etl.py +0 -0
  52. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/ai/memory.py +0 -0
  53. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/ai/observability.py +0 -0
  54. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/ai/providers.py +0 -0
  55. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/ai/resilience.py +0 -0
  56. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/ai/tools.py +0 -0
  57. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/ai/vectorstore.py +0 -0
  58. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/annotations/batch.py +0 -0
  59. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/annotations/cache.py +0 -0
  60. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/annotations/cloud.py +0 -0
  61. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/annotations/data.py +0 -0
  62. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/annotations/enterprise.py +0 -0
  63. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/annotations/langchain.py +0 -0
  64. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/annotations/langgraph.py +0 -0
  65. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/annotations/lombok.py +0 -0
  66. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/annotations/messaging.py +0 -0
  67. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/annotations/security.py +0 -0
  68. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/aop/__init__.py +0 -0
  69. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/aop/cloud_aop.py +0 -0
  70. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/aop/comprehensive_aop.py +0 -0
  71. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/aop/method_interceptor.py +0 -0
  72. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/aop/proxy_factory.py +0 -0
  73. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/batch/__init__.py +0 -0
  74. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/cli/__init__.py +0 -0
  75. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/cli/main.py +0 -0
  76. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/cli/scaffold.py +0 -0
  77. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/cloud/__init__.py +0 -0
  78. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/cloud/bus.py +0 -0
  79. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/cloud/config_center.py +0 -0
  80. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/cloud/discovery.py +0 -0
  81. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/cloud/feign.py +0 -0
  82. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/cloud/gateway.py +0 -0
  83. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/cloud/load_balancer.py +0 -0
  84. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/cloud/nacos_config.py +0 -0
  85. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/cloud/seata.py +0 -0
  86. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/cloud/seata_at_proxy.py +0 -0
  87. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/cloud/seata_bridge.py +0 -0
  88. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/cloud/sentinel.py +0 -0
  89. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/cloud/tracer.py +0 -0
  90. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/cloud/transaction_store.py +0 -0
  91. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/config/__init__.py +0 -0
  92. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/config/binding.py +0 -0
  93. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/config/config_loader.py +0 -0
  94. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/config/spring-configuration-metadata.json +0 -0
  95. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/context/__init__.py +0 -0
  96. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/context/application_context.py +0 -0
  97. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/context/bean_definition.py +0 -0
  98. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/context/registry.py +0 -0
  99. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/context/scanner.py +0 -0
  100. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/core/__init__.py +0 -0
  101. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/core/graceful_shutdown.py +0 -0
  102. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/core/typing_utils.py +0 -0
  103. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/csv/annotations.py +0 -0
  104. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/csv/converters.py +0 -0
  105. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/csv/easy_csv.py +0 -0
  106. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/csv/exceptions.py +0 -0
  107. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/csv/reader.py +0 -0
  108. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/csv/writer.py +0 -0
  109. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/data/page.py +0 -0
  110. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/data/repository.py +0 -0
  111. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/data/rest.py +0 -0
  112. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/data/specification.py +0 -0
  113. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/datasource/annotations.py +0 -0
  114. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/datasource/context.py +0 -0
  115. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/datasource/dynamic.py +0 -0
  116. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/devtools.py +0 -0
  117. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/event/__init__.py +0 -0
  118. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/event/publisher.py +0 -0
  119. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/excel/annotations.py +0 -0
  120. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/excel/converters.py +0 -0
  121. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/excel/easy_excel.py +0 -0
  122. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/excel/exceptions.py +0 -0
  123. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/excel/reader.py +0 -0
  124. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/excel/style.py +0 -0
  125. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/excel/writer.py +0 -0
  126. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/i18n/accessor.py +0 -0
  127. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/i18n/auto_config.py +0 -0
  128. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/i18n/holder.py +0 -0
  129. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/i18n/locale.py +0 -0
  130. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/i18n/locale_resolver.py +0 -0
  131. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/i18n/message_source.py +0 -0
  132. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/i18n/middleware.py +0 -0
  133. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/i18n/properties.py +0 -0
  134. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/i18n/sources.py +0 -0
  135. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/langchain/adapters.py +0 -0
  136. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/langchain/agents/__init__.py +0 -0
  137. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/langchain/agents/services.py +0 -0
  138. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/langchain/annotations.py +0 -0
  139. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/langchain/autoconfig.py +0 -0
  140. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/langchain/callbacks/__init__.py +0 -0
  141. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/langchain/callbacks/handlers.py +0 -0
  142. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/langchain/chains/__init__.py +0 -0
  143. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/langchain/chains/services.py +0 -0
  144. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/langchain/core.py +0 -0
  145. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/langchain/indexes/__init__.py +0 -0
  146. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/langchain/indexes/index.py +0 -0
  147. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/langchain/loaders/__init__.py +0 -0
  148. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/langchain/loaders/loaders.py +0 -0
  149. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/langchain/memory/__init__.py +0 -0
  150. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/langchain/memory/memory.py +0 -0
  151. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/langchain/parsers/__init__.py +0 -0
  152. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/langchain/parsers/parsers.py +0 -0
  153. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/langchain/partners.py +0 -0
  154. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/langchain/prompts/__init__.py +0 -0
  155. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/langchain/prompts/templates.py +0 -0
  156. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/langchain/retrievers/__init__.py +0 -0
  157. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/langchain/retrievers/retrievers.py +0 -0
  158. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/langchain/tools/__init__.py +0 -0
  159. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/langchain/tools/tools.py +0 -0
  160. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/langchain/utilities/__init__.py +0 -0
  161. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/langchain/utilities/utils.py +0 -0
  162. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/langchain/vectorstores/__init__.py +0 -0
  163. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/langchain/vectorstores/stores.py +0 -0
  164. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/langgraph/__init__.py +0 -0
  165. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/langgraph/annotation_runtime.py +0 -0
  166. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/langgraph/annotations.py +0 -0
  167. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/langgraph/autoconfig.py +0 -0
  168. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/langgraph/checkpoint.py +0 -0
  169. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/langgraph/config.py +0 -0
  170. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/langgraph/runtime.py +0 -0
  171. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/logging/__init__.py +0 -0
  172. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/main.py +0 -0
  173. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/mcp/__init__.py +0 -0
  174. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/mcp/annotation_runtime.py +0 -0
  175. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/mcp/annotations.py +0 -0
  176. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/mcp/autoconfig.py +0 -0
  177. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/mcp/client.py +0 -0
  178. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/mcp/config.py +0 -0
  179. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/mcp/server.py +0 -0
  180. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/messaging/__init__.py +0 -0
  181. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/messaging/kafka.py +0 -0
  182. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/messaging/rabbitmq.py +0 -0
  183. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/monitoring/__init__.py +0 -0
  184. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/monitoring/admin_client.py +0 -0
  185. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/monitoring/prometheus.py +0 -0
  186. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/orm/__init__.py +0 -0
  187. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/orm/database.py +0 -0
  188. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/orm/ddl_auto.py +0 -0
  189. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/orm/migration.py +0 -0
  190. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/orm/mybatis_integration.py +0 -0
  191. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/orm/pymybatis/annotations/__init__.py +0 -0
  192. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/orm/pymybatis/annotations/annotations.py +0 -0
  193. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/orm/pymybatis/cache/__init__.py +0 -0
  194. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/orm/pymybatis/cache/cache.py +0 -0
  195. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/orm/pymybatis/cache/redis_cache.py +0 -0
  196. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/orm/pymybatis/circuit_breaker/__init__.py +0 -0
  197. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/orm/pymybatis/circuit_breaker/circuit_breaker.py +0 -0
  198. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/orm/pymybatis/configuration.py +0 -0
  199. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/orm/pymybatis/core/__init__.py +0 -0
  200. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/orm/pymybatis/core/sql_session.py +0 -0
  201. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/orm/pymybatis/core/sql_session_factory.py +0 -0
  202. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/orm/pymybatis/dialect/__init__.py +0 -0
  203. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/orm/pymybatis/dialect/dialect.py +0 -0
  204. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/orm/pymybatis/dynamic_sql/__init__.py +0 -0
  205. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/orm/pymybatis/dynamic_sql/dynamic_sql.py +0 -0
  206. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/orm/pymybatis/interceptor/__init__.py +0 -0
  207. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/orm/pymybatis/interceptor/interceptor.py +0 -0
  208. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/orm/pymybatis/mapper/__init__.py +0 -0
  209. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/orm/pymybatis/mapper/mapper.py +0 -0
  210. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/orm/pymybatis/metrics/__init__.py +0 -0
  211. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/orm/pymybatis/metrics/metrics.py +0 -0
  212. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/orm/pymybatis/pool/__init__.py +0 -0
  213. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/orm/pymybatis/pool/connection_pool.py +0 -0
  214. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/orm/pymybatis/security/__init__.py +0 -0
  215. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/orm/pymybatis/security/access_control.py +0 -0
  216. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/orm/pymybatis/security/password_encoder.py +0 -0
  217. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/orm/pymybatis/security/sensitive_data_masker.py +0 -0
  218. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/orm/pymybatis/security/sql_injection_detector.py +0 -0
  219. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/orm/pymybatis/transaction/__init__.py +0 -0
  220. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/orm/pymybatis/transaction/transaction.py +0 -0
  221. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/orm/pymybatis/type_handler/__init__.py +0 -0
  222. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/orm/pymybatis/type_handler/type_handler.py +0 -0
  223. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/orm/pymybatis/xml_parser/__init__.py +0 -0
  224. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/orm/pymybatis/xml_parser/xml_parser.py +0 -0
  225. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/retry/__init__.py +0 -0
  226. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/retry/recovery.py +0 -0
  227. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/retry/retry_annotations.py +0 -0
  228. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/retry/retry_decorator.py +0 -0
  229. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/scheduling/__init__.py +0 -0
  230. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/scheduling/scheduler.py +0 -0
  231. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/security/__init__.py +0 -0
  232. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/security/jwt_utils.py +0 -0
  233. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/security/oauth2.py +0 -0
  234. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/security/replay_protection.py +0 -0
  235. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/security/security_aop.py +0 -0
  236. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/security/security_context.py +0 -0
  237. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/test/slicing.py +0 -0
  238. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/tracing/__init__.py +0 -0
  239. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/tracing/skywalking.py +0 -0
  240. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/tx/events.py +0 -0
  241. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/tx/synchronization.py +0 -0
  242. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/utils/__init__.py +0 -0
  243. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/utils/bean_utils.py +0 -0
  244. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/utils/logger.py +0 -0
  245. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/utils/redis_client.py +0 -0
  246. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/validation/aop.py +0 -0
  247. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/validation/constraints.py +0 -0
  248. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/validation/exceptions.py +0 -0
  249. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/validation/validator.py +0 -0
  250. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/web/__init__.py +0 -0
  251. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/web/actuator.py +0 -0
  252. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/web/csrf.py +0 -0
  253. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/web/exception_handler.py +0 -0
  254. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/web/hateoas.py +0 -0
  255. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/web/health.py +0 -0
  256. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/web/interceptor.py +0 -0
  257. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/web/request_metrics.py +0 -0
  258. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/web/result.py +0 -0
  259. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/web/swagger.py +0 -0
  260. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/web/web_context.py +0 -0
  261. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/websocket/annotations.py +0 -0
  262. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/websocket/broker.py +0 -0
  263. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/websocket/exceptions.py +0 -0
  264. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/websocket/handler.py +0 -0
  265. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/websocket/router.py +0 -0
  266. {springbootai-2.3.4 → springbootai-2.3.5}/springbootai/websocket/session.py +0 -0
  267. {springbootai-2.3.4 → springbootai-2.3.5}/sql/seata_undo_log.sql +0 -0
  268. {springbootai-2.3.4 → springbootai-2.3.5}/tests/test_actuator.py +0 -0
  269. {springbootai-2.3.4 → springbootai-2.3.5}/tests/test_actuator_prometheus_admin.py +0 -0
  270. {springbootai-2.3.4 → springbootai-2.3.5}/tests/test_ai_annotations.py +0 -0
  271. {springbootai-2.3.4 → springbootai-2.3.5}/tests/test_ai_comprehensive.py +0 -0
  272. {springbootai-2.3.4 → springbootai-2.3.5}/tests/test_ai_declarative_annotations.py +0 -0
  273. {springbootai-2.3.4 → springbootai-2.3.5}/tests/test_ai_module.py +0 -0
  274. {springbootai-2.3.4 → springbootai-2.3.5}/tests/test_annotation_combinations.py +0 -0
  275. {springbootai-2.3.4 → springbootai-2.3.5}/tests/test_aop_annotations_full.py +0 -0
  276. {springbootai-2.3.4 → springbootai-2.3.5}/tests/test_audit_time.py +0 -0
  277. {springbootai-2.3.4 → springbootai-2.3.5}/tests/test_batch.py +0 -0
  278. {springbootai-2.3.4 → springbootai-2.3.5}/tests/test_bean_utils.py +0 -0
  279. {springbootai-2.3.4 → springbootai-2.3.5}/tests/test_bus.py +0 -0
  280. {springbootai-2.3.4 → springbootai-2.3.5}/tests/test_cache_annotations.py +0 -0
  281. {springbootai-2.3.4 → springbootai-2.3.5}/tests/test_cli.py +0 -0
  282. {springbootai-2.3.4 → springbootai-2.3.5}/tests/test_cloud_embedded_full.py +0 -0
  283. {springbootai-2.3.4 → springbootai-2.3.5}/tests/test_component_init_error.py +0 -0
  284. {springbootai-2.3.4 → springbootai-2.3.5}/tests/test_compositional_annotations.py +0 -0
  285. {springbootai-2.3.4 → springbootai-2.3.5}/tests/test_conditional_annotations.py +0 -0
  286. {springbootai-2.3.4 → springbootai-2.3.5}/tests/test_config_binding.py +0 -0
  287. {springbootai-2.3.4 → springbootai-2.3.5}/tests/test_config_center.py +0 -0
  288. {springbootai-2.3.4 → springbootai-2.3.5}/tests/test_config_fixes_185.py +0 -0
  289. {springbootai-2.3.4 → springbootai-2.3.5}/tests/test_connection_resilience.py +0 -0
  290. {springbootai-2.3.4 → springbootai-2.3.5}/tests/test_core.py +0 -0
  291. {springbootai-2.3.4 → springbootai-2.3.5}/tests/test_core_annotations_full.py +0 -0
  292. {springbootai-2.3.4 → springbootai-2.3.5}/tests/test_csrf.py +0 -0
  293. {springbootai-2.3.4 → springbootai-2.3.5}/tests/test_csv_module.py +0 -0
  294. {springbootai-2.3.4 → springbootai-2.3.5}/tests/test_data_repository.py +0 -0
  295. {springbootai-2.3.4 → springbootai-2.3.5}/tests/test_data_rest.py +0 -0
  296. {springbootai-2.3.4 → springbootai-2.3.5}/tests/test_datasource_routing.py +0 -0
  297. {springbootai-2.3.4 → springbootai-2.3.5}/tests/test_ddl_auto.py +0 -0
  298. {springbootai-2.3.4 → springbootai-2.3.5}/tests/test_declarative_aop_post_authorize_recover.py +0 -0
  299. {springbootai-2.3.4 → springbootai-2.3.5}/tests/test_devtools.py +0 -0
  300. {springbootai-2.3.4 → springbootai-2.3.5}/tests/test_di_config_event_full.py +0 -0
  301. {springbootai-2.3.4 → springbootai-2.3.5}/tests/test_excel_module.py +0 -0
  302. {springbootai-2.3.4 → springbootai-2.3.5}/tests/test_hateoas.py +0 -0
  303. {springbootai-2.3.4 → springbootai-2.3.5}/tests/test_i18n_module.py +0 -0
  304. {springbootai-2.3.4 → springbootai-2.3.5}/tests/test_jpa_version_transient.py +0 -0
  305. {springbootai-2.3.4 → springbootai-2.3.5}/tests/test_kafka.py +0 -0
  306. {springbootai-2.3.4 → springbootai-2.3.5}/tests/test_langchain_comprehensive.py +0 -0
  307. {springbootai-2.3.4 → springbootai-2.3.5}/tests/test_langchain_ext.py +0 -0
  308. {springbootai-2.3.4 → springbootai-2.3.5}/tests/test_langchain_module.py +0 -0
  309. {springbootai-2.3.4 → springbootai-2.3.5}/tests/test_langgraph_comprehensive.py +0 -0
  310. {springbootai-2.3.4 → springbootai-2.3.5}/tests/test_langgraph_module.py +0 -0
  311. {springbootai-2.3.4 → springbootai-2.3.5}/tests/test_logging_config.py +0 -0
  312. {springbootai-2.3.4 → springbootai-2.3.5}/tests/test_lombok_annotations.py +0 -0
  313. {springbootai-2.3.4 → springbootai-2.3.5}/tests/test_mcp_module.py +0 -0
  314. {springbootai-2.3.4 → springbootai-2.3.5}/tests/test_metadata.py +0 -0
  315. {springbootai-2.3.4 → springbootai-2.3.5}/tests/test_migration.py +0 -0
  316. {springbootai-2.3.4 → springbootai-2.3.5}/tests/test_nacos_config.py +0 -0
  317. {springbootai-2.3.4 → springbootai-2.3.5}/tests/test_new_annotations.py +0 -0
  318. {springbootai-2.3.4 → springbootai-2.3.5}/tests/test_new_features.py +0 -0
  319. {springbootai-2.3.4 → springbootai-2.3.5}/tests/test_oauth2.py +0 -0
  320. {springbootai-2.3.4 → springbootai-2.3.5}/tests/test_orm_pymybatis_full.py +0 -0
  321. {springbootai-2.3.4 → springbootai-2.3.5}/tests/test_production_readiness.py +0 -0
  322. {springbootai-2.3.4 → springbootai-2.3.5}/tests/test_pymybatis_configuration_hardening.py +0 -0
  323. {springbootai-2.3.4 → springbootai-2.3.5}/tests/test_pymybatis_contract.py +0 -0
  324. {springbootai-2.3.4 → springbootai-2.3.5}/tests/test_request_metrics.py +0 -0
  325. {springbootai-2.3.4 → springbootai-2.3.5}/tests/test_retry.py +0 -0
  326. {springbootai-2.3.4 → springbootai-2.3.5}/tests/test_runtime_configuration_fixes.py +0 -0
  327. {springbootai-2.3.4 → springbootai-2.3.5}/tests/test_scaffold_hardening.py +0 -0
  328. {springbootai-2.3.4 → springbootai-2.3.5}/tests/test_scheduling.py +0 -0
  329. {springbootai-2.3.4 → springbootai-2.3.5}/tests/test_seata_at_proxy.py +0 -0
  330. {springbootai-2.3.4 → springbootai-2.3.5}/tests/test_seata_bridge.py +0 -0
  331. {springbootai-2.3.4 → springbootai-2.3.5}/tests/test_seata_durable_store.py +0 -0
  332. {springbootai-2.3.4 → springbootai-2.3.5}/tests/test_security.py +0 -0
  333. {springbootai-2.3.4 → springbootai-2.3.5}/tests/test_security_full.py +0 -0
  334. {springbootai-2.3.4 → springbootai-2.3.5}/tests/test_security_hardening.py +0 -0
  335. {springbootai-2.3.4 → springbootai-2.3.5}/tests/test_select_page.py +0 -0
  336. {springbootai-2.3.4 → springbootai-2.3.5}/tests/test_starter.py +0 -0
  337. {springbootai-2.3.4 → springbootai-2.3.5}/tests/test_startup_lifecycle.py +0 -0
  338. {springbootai-2.3.4 → springbootai-2.3.5}/tests/test_swagger_module.py +0 -0
  339. {springbootai-2.3.4 → springbootai-2.3.5}/tests/test_test_slicing.py +0 -0
  340. {springbootai-2.3.4 → springbootai-2.3.5}/tests/test_tracing.py +0 -0
  341. {springbootai-2.3.4 → springbootai-2.3.5}/tests/test_transactional_events.py +0 -0
  342. {springbootai-2.3.4 → springbootai-2.3.5}/tests/test_validation_module.py +0 -0
  343. {springbootai-2.3.4 → springbootai-2.3.5}/tests/test_web_annotations_full.py +0 -0
  344. {springbootai-2.3.4 → springbootai-2.3.5}/tests/test_web_file_upload.py +0 -0
  345. {springbootai-2.3.4 → springbootai-2.3.5}/tests/test_web_root_mapping.py +0 -0
  346. {springbootai-2.3.4 → springbootai-2.3.5}/tests/test_web_security_responses.py +0 -0
  347. {springbootai-2.3.4 → springbootai-2.3.5}/tests/test_web_static_files.py +0 -0
  348. {springbootai-2.3.4 → springbootai-2.3.5}/tests/test_websocket_module.py +0 -0
@@ -1,5 +1,13 @@
1
1
  # Changelog
2
2
 
3
+ ## [2.3.5] - 2026-08-20
4
+
5
+ ### 文档与发布
6
+
7
+ - 发布版本升级到 `2.3.5`,同步框架主包、扩展模块、PyMyBatis 内嵌版本、README 版本矩阵和打包元数据。
8
+ - README 首页新增 SpringBootAI 在线考试认证与证书说明,提供认证入口、适用场景、备考流程和重点知识范围。
9
+ - 认证平台入口:[http://www.yucg.cn:8230](http://www.yucg.cn:8230)。
10
+
3
11
  ## [2.3.4] - 2026-08-19
4
12
 
5
13
  ### 新增与完善
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: springbootAI
3
- Version: 2.3.4
3
+ Version: 2.3.5
4
4
  Summary: Spring-style Python framework with Web, ORM, Cloud and AI integrations
5
5
  Author-email: YuConggen <1516933915@qq.com>
6
6
  License-Expression: MIT
@@ -163,9 +163,41 @@ Dynamic: license-file
163
163
  # SpringBootAI
164
164
 
165
165
  <p align="center">
166
- <img src="doc/images/hero-banner.png" alt="SpringBootAI 功能总览" width="100%" />
166
+ <img src="https://raw.githubusercontent.com/YUCONGGEN/springbootAI/master/doc/images/hero-banner.png" alt="SpringBootAI 功能总览" width="100%" />
167
167
  </p>
168
168
 
169
+ ## SpringBootAI 考试认证与证书
170
+
171
+ SpringBootAI 已提供配套的在线考试认证平台,学习者、团队成员和项目使用方可以通过认证考试检验自己对框架核心能力的掌握情况,并在通过考试后获得对应证书。
172
+
173
+ 认证入口:[http://www.yucg.cn:8230](http://www.yucg.cn:8230)
174
+
175
+ 认证适合以下场景:
176
+
177
+ - **个人学习证明**:用于记录自己已经系统学习 SpringBootAI 的 Web、IoC、配置、数据访问、AOP、AI 扩展和生产治理等核心内容。
178
+ - **团队能力评估**:团队引入 SpringBootAI 前,可以让成员通过统一考试确认基础概念、开发规范和常见问题处理能力。
179
+ - **项目交付背书**:在培训、内部推广、项目验收或技术选型说明中,证书可作为使用者熟悉框架体系和最佳实践的辅助证明。
180
+ - **持续学习路径**:认证内容覆盖从入门到进阶的关键知识点,适合结合 README、模块文档和示例工程逐步学习后再参加考试。
181
+
182
+ 建议的认证准备流程:
183
+
184
+ 1. 先按 README 中的“10 分钟跑通第一个接口”完成本地环境搭建,确认能够创建应用、启动服务并访问 Swagger。
185
+ 2. 阅读 [新手指南](https://github.com/YUCONGGEN/springbootAI/blob/master/doc/BEGINNER_GUIDE.md),理解 `@SpringBootApplication`、`@RestController`、`@Service`、`@Autowired`、配置文件和依赖注入的基本用法。
186
+ 3. 根据实际使用方向阅读模块文档,例如 Web MVC、ORM、事务、缓存、安全、配置绑定、测试切片、AI、LangChain、LangGraph、MCP 和 Cloud 微服务等。
187
+ 4. 运行示例或编写一个小型业务接口,至少覆盖 Controller、Service、配置读取、异常处理、Swagger 文档和数据访问中的若干能力。
188
+ 5. 访问认证平台参加考试,通过后按平台页面提示查看、下载或领取证书。证书信息、考试规则、题量、通过标准和有效期以认证平台展示为准。
189
+
190
+ 认证重点建议关注:
191
+
192
+ | 方向 | 建议掌握内容 |
193
+ |---|---|
194
+ | 快速入门 | 安装方式、项目结构、启动入口、扫描包、`application.yml`、Swagger 访问 |
195
+ | Web 与 IoC | 路由映射、参数绑定、Controller/Service 分层、Bean 注册、依赖注入、生命周期 |
196
+ | 数据与事务 | PyMyBatis Mapper、XML Mapper、分页、动态 SQL、事务边界、回滚行为 |
197
+ | 工程治理 | 配置合并、Profile、日志、健康检查、Prometheus、限流、熔断、测试切片 |
198
+ | 安全能力 | JWT、密码加密、SQL 注入防护、CSRF、OAuth2、访问控制与常见错误处理 |
199
+ | AI 生态 | ChatClient、Tools、RAG、Advisor、LangChain、LangGraph、MCP client/server |
200
+
169
201
  [![PyPI](https://img.shields.io/pypi/v/springbootAI)](https://pypi.org/project/springbootAI/)
170
202
  [![Python](https://img.shields.io/pypi/pyversions/springbootAI)](https://pypi.org/project/springbootAI/)
171
203
  [![CI](https://github.com/YUCONGGEN/springbootAI/actions/workflows/ci.yml/badge.svg?branch=master)](https://github.com/YUCONGGEN/springbootAI/actions/workflows/ci.yml)
@@ -183,7 +215,7 @@ SpringBootAI 是一个采用 Spring 风格注解和分层结构的 Python 应用
183
215
  | AI 与编排 | 模型调用、Tools、RAG、Chain、状态图、MCP client/server | LangChain / LangGraph / 官方 MCP SDK |
184
216
  | 生产治理 | 健康检查、Prometheus、限流熔断、追踪、Swagger | prometheus-client / OpenTelemetry / OpenAPI |
185
217
 
186
- 当前版本是 `2.3.2`;支持 Python 3.10、3.11 和 3.12,许可证为 MIT。项目仍标记为 Beta。用于公网高并发、合规敏感或支付/订单/库存等核心系统前,必须完成目标数据库、流量模型、故障恢复和安全基线验证。内嵌 Gateway 适合内部路由,不替代公网 Nginx/Kong/WAF;Seata `distributed` 对接官方 TC + TCC 回调;`at` 模式通过 ORM 拦截器自动生成 undo_log 实现自动回滚。
218
+ 当前版本是 `2.3.5`;支持 Python 3.10、3.11 和 3.12,许可证为 MIT。项目仍标记为 Beta。用于公网高并发、合规敏感或支付/订单/库存等核心系统前,必须完成目标数据库、流量模型、故障恢复和安全基线验证。内嵌 Gateway 适合内部路由,不替代公网 Nginx/Kong/WAF;Seata `distributed` 对接官方 TC + TCC 回调;`at` 模式通过 ORM 拦截器自动生成 undo_log 实现自动回滚。
187
219
 
188
220
  [新手指南](https://github.com/YUCONGGEN/springbootAI/blob/master/doc/BEGINNER_GUIDE.md) | [全部文档](https://github.com/YUCONGGEN/springbootAI/tree/master/doc) | [变更日志](https://github.com/YUCONGGEN/springbootAI/blob/master/CHANGELOG.md) | [安全报告](https://github.com/YUCONGGEN/springbootAI/blob/master/SECURITY.md) | [发布检查](https://github.com/YUCONGGEN/springbootAI/blob/master/doc/RELEASE_CHECKLIST.md)
189
221
 
@@ -364,10 +396,10 @@ SpringBootAI 是一个 **Python Web 框架**。它把 Java Spring Boot 的"注
364
396
 
365
397
  | 组件 | 当前版本 |
366
398
  |------|----------|
367
- | `springbootai` 框架 API | 2.3.2 |
368
- | `springbootai.orm.pymybatis` | 2.3.2 |
369
- | `springbootai.ai` AI 模块 | 2.3.2 |
370
- | `springbootai.langchain` LangChain 模块 | 2.3.2 |
399
+ | `springbootai` 框架 API | 2.3.5 |
400
+ | `springbootai.orm.pymybatis` | 2.3.5 |
401
+ | `springbootai.ai` AI 模块 | 2.3.5 |
402
+ | `springbootai.langchain` LangChain 模块 | 2.3.5 |
371
403
  | Python | 3.10+ |
372
404
 
373
405
  ### 1.4 适合什么场景
@@ -1,9 +1,41 @@
1
1
  # SpringBootAI
2
2
 
3
3
  <p align="center">
4
- <img src="doc/images/hero-banner.png" alt="SpringBootAI 功能总览" width="100%" />
4
+ <img src="https://raw.githubusercontent.com/YUCONGGEN/springbootAI/master/doc/images/hero-banner.png" alt="SpringBootAI 功能总览" width="100%" />
5
5
  </p>
6
6
 
7
+ ## SpringBootAI 考试认证与证书
8
+
9
+ SpringBootAI 已提供配套的在线考试认证平台,学习者、团队成员和项目使用方可以通过认证考试检验自己对框架核心能力的掌握情况,并在通过考试后获得对应证书。
10
+
11
+ 认证入口:[http://www.yucg.cn:8230](http://www.yucg.cn:8230)
12
+
13
+ 认证适合以下场景:
14
+
15
+ - **个人学习证明**:用于记录自己已经系统学习 SpringBootAI 的 Web、IoC、配置、数据访问、AOP、AI 扩展和生产治理等核心内容。
16
+ - **团队能力评估**:团队引入 SpringBootAI 前,可以让成员通过统一考试确认基础概念、开发规范和常见问题处理能力。
17
+ - **项目交付背书**:在培训、内部推广、项目验收或技术选型说明中,证书可作为使用者熟悉框架体系和最佳实践的辅助证明。
18
+ - **持续学习路径**:认证内容覆盖从入门到进阶的关键知识点,适合结合 README、模块文档和示例工程逐步学习后再参加考试。
19
+
20
+ 建议的认证准备流程:
21
+
22
+ 1. 先按 README 中的“10 分钟跑通第一个接口”完成本地环境搭建,确认能够创建应用、启动服务并访问 Swagger。
23
+ 2. 阅读 [新手指南](https://github.com/YUCONGGEN/springbootAI/blob/master/doc/BEGINNER_GUIDE.md),理解 `@SpringBootApplication`、`@RestController`、`@Service`、`@Autowired`、配置文件和依赖注入的基本用法。
24
+ 3. 根据实际使用方向阅读模块文档,例如 Web MVC、ORM、事务、缓存、安全、配置绑定、测试切片、AI、LangChain、LangGraph、MCP 和 Cloud 微服务等。
25
+ 4. 运行示例或编写一个小型业务接口,至少覆盖 Controller、Service、配置读取、异常处理、Swagger 文档和数据访问中的若干能力。
26
+ 5. 访问认证平台参加考试,通过后按平台页面提示查看、下载或领取证书。证书信息、考试规则、题量、通过标准和有效期以认证平台展示为准。
27
+
28
+ 认证重点建议关注:
29
+
30
+ | 方向 | 建议掌握内容 |
31
+ |---|---|
32
+ | 快速入门 | 安装方式、项目结构、启动入口、扫描包、`application.yml`、Swagger 访问 |
33
+ | Web 与 IoC | 路由映射、参数绑定、Controller/Service 分层、Bean 注册、依赖注入、生命周期 |
34
+ | 数据与事务 | PyMyBatis Mapper、XML Mapper、分页、动态 SQL、事务边界、回滚行为 |
35
+ | 工程治理 | 配置合并、Profile、日志、健康检查、Prometheus、限流、熔断、测试切片 |
36
+ | 安全能力 | JWT、密码加密、SQL 注入防护、CSRF、OAuth2、访问控制与常见错误处理 |
37
+ | AI 生态 | ChatClient、Tools、RAG、Advisor、LangChain、LangGraph、MCP client/server |
38
+
7
39
  [![PyPI](https://img.shields.io/pypi/v/springbootAI)](https://pypi.org/project/springbootAI/)
8
40
  [![Python](https://img.shields.io/pypi/pyversions/springbootAI)](https://pypi.org/project/springbootAI/)
9
41
  [![CI](https://github.com/YUCONGGEN/springbootAI/actions/workflows/ci.yml/badge.svg?branch=master)](https://github.com/YUCONGGEN/springbootAI/actions/workflows/ci.yml)
@@ -21,7 +53,7 @@ SpringBootAI 是一个采用 Spring 风格注解和分层结构的 Python 应用
21
53
  | AI 与编排 | 模型调用、Tools、RAG、Chain、状态图、MCP client/server | LangChain / LangGraph / 官方 MCP SDK |
22
54
  | 生产治理 | 健康检查、Prometheus、限流熔断、追踪、Swagger | prometheus-client / OpenTelemetry / OpenAPI |
23
55
 
24
- 当前版本是 `2.3.2`;支持 Python 3.10、3.11 和 3.12,许可证为 MIT。项目仍标记为 Beta。用于公网高并发、合规敏感或支付/订单/库存等核心系统前,必须完成目标数据库、流量模型、故障恢复和安全基线验证。内嵌 Gateway 适合内部路由,不替代公网 Nginx/Kong/WAF;Seata `distributed` 对接官方 TC + TCC 回调;`at` 模式通过 ORM 拦截器自动生成 undo_log 实现自动回滚。
56
+ 当前版本是 `2.3.5`;支持 Python 3.10、3.11 和 3.12,许可证为 MIT。项目仍标记为 Beta。用于公网高并发、合规敏感或支付/订单/库存等核心系统前,必须完成目标数据库、流量模型、故障恢复和安全基线验证。内嵌 Gateway 适合内部路由,不替代公网 Nginx/Kong/WAF;Seata `distributed` 对接官方 TC + TCC 回调;`at` 模式通过 ORM 拦截器自动生成 undo_log 实现自动回滚。
25
57
 
26
58
  [新手指南](https://github.com/YUCONGGEN/springbootAI/blob/master/doc/BEGINNER_GUIDE.md) | [全部文档](https://github.com/YUCONGGEN/springbootAI/tree/master/doc) | [变更日志](https://github.com/YUCONGGEN/springbootAI/blob/master/CHANGELOG.md) | [安全报告](https://github.com/YUCONGGEN/springbootAI/blob/master/SECURITY.md) | [发布检查](https://github.com/YUCONGGEN/springbootAI/blob/master/doc/RELEASE_CHECKLIST.md)
27
59
 
@@ -202,10 +234,10 @@ SpringBootAI 是一个 **Python Web 框架**。它把 Java Spring Boot 的"注
202
234
 
203
235
  | 组件 | 当前版本 |
204
236
  |------|----------|
205
- | `springbootai` 框架 API | 2.3.2 |
206
- | `springbootai.orm.pymybatis` | 2.3.2 |
207
- | `springbootai.ai` AI 模块 | 2.3.2 |
208
- | `springbootai.langchain` LangChain 模块 | 2.3.2 |
237
+ | `springbootai` 框架 API | 2.3.5 |
238
+ | `springbootai.orm.pymybatis` | 2.3.5 |
239
+ | `springbootai.ai` AI 模块 | 2.3.5 |
240
+ | `springbootai.langchain` LangChain 模块 | 2.3.5 |
209
241
  | Python | 3.10+ |
210
242
 
211
243
  ### 1.4 适合什么场景
@@ -12,7 +12,7 @@ build-backend = "setuptools.build_meta"
12
12
  [project]
13
13
  # Distribution name: springbootAI (pip install springbootAI); import package: springbootai.
14
14
  name = "springbootAI"
15
- version = "2.3.4"
15
+ version = "2.3.5"
16
16
  description = "Spring-style Python framework with Web, ORM, Cloud and AI integrations"
17
17
  readme = "README.md"
18
18
  license = "MIT"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: springbootAI
3
- Version: 2.3.4
3
+ Version: 2.3.5
4
4
  Summary: Spring-style Python framework with Web, ORM, Cloud and AI integrations
5
5
  Author-email: YuConggen <1516933915@qq.com>
6
6
  License-Expression: MIT
@@ -163,9 +163,41 @@ Dynamic: license-file
163
163
  # SpringBootAI
164
164
 
165
165
  <p align="center">
166
- <img src="doc/images/hero-banner.png" alt="SpringBootAI 功能总览" width="100%" />
166
+ <img src="https://raw.githubusercontent.com/YUCONGGEN/springbootAI/master/doc/images/hero-banner.png" alt="SpringBootAI 功能总览" width="100%" />
167
167
  </p>
168
168
 
169
+ ## SpringBootAI 考试认证与证书
170
+
171
+ SpringBootAI 已提供配套的在线考试认证平台,学习者、团队成员和项目使用方可以通过认证考试检验自己对框架核心能力的掌握情况,并在通过考试后获得对应证书。
172
+
173
+ 认证入口:[http://www.yucg.cn:8230](http://www.yucg.cn:8230)
174
+
175
+ 认证适合以下场景:
176
+
177
+ - **个人学习证明**:用于记录自己已经系统学习 SpringBootAI 的 Web、IoC、配置、数据访问、AOP、AI 扩展和生产治理等核心内容。
178
+ - **团队能力评估**:团队引入 SpringBootAI 前,可以让成员通过统一考试确认基础概念、开发规范和常见问题处理能力。
179
+ - **项目交付背书**:在培训、内部推广、项目验收或技术选型说明中,证书可作为使用者熟悉框架体系和最佳实践的辅助证明。
180
+ - **持续学习路径**:认证内容覆盖从入门到进阶的关键知识点,适合结合 README、模块文档和示例工程逐步学习后再参加考试。
181
+
182
+ 建议的认证准备流程:
183
+
184
+ 1. 先按 README 中的“10 分钟跑通第一个接口”完成本地环境搭建,确认能够创建应用、启动服务并访问 Swagger。
185
+ 2. 阅读 [新手指南](https://github.com/YUCONGGEN/springbootAI/blob/master/doc/BEGINNER_GUIDE.md),理解 `@SpringBootApplication`、`@RestController`、`@Service`、`@Autowired`、配置文件和依赖注入的基本用法。
186
+ 3. 根据实际使用方向阅读模块文档,例如 Web MVC、ORM、事务、缓存、安全、配置绑定、测试切片、AI、LangChain、LangGraph、MCP 和 Cloud 微服务等。
187
+ 4. 运行示例或编写一个小型业务接口,至少覆盖 Controller、Service、配置读取、异常处理、Swagger 文档和数据访问中的若干能力。
188
+ 5. 访问认证平台参加考试,通过后按平台页面提示查看、下载或领取证书。证书信息、考试规则、题量、通过标准和有效期以认证平台展示为准。
189
+
190
+ 认证重点建议关注:
191
+
192
+ | 方向 | 建议掌握内容 |
193
+ |---|---|
194
+ | 快速入门 | 安装方式、项目结构、启动入口、扫描包、`application.yml`、Swagger 访问 |
195
+ | Web 与 IoC | 路由映射、参数绑定、Controller/Service 分层、Bean 注册、依赖注入、生命周期 |
196
+ | 数据与事务 | PyMyBatis Mapper、XML Mapper、分页、动态 SQL、事务边界、回滚行为 |
197
+ | 工程治理 | 配置合并、Profile、日志、健康检查、Prometheus、限流、熔断、测试切片 |
198
+ | 安全能力 | JWT、密码加密、SQL 注入防护、CSRF、OAuth2、访问控制与常见错误处理 |
199
+ | AI 生态 | ChatClient、Tools、RAG、Advisor、LangChain、LangGraph、MCP client/server |
200
+
169
201
  [![PyPI](https://img.shields.io/pypi/v/springbootAI)](https://pypi.org/project/springbootAI/)
170
202
  [![Python](https://img.shields.io/pypi/pyversions/springbootAI)](https://pypi.org/project/springbootAI/)
171
203
  [![CI](https://github.com/YUCONGGEN/springbootAI/actions/workflows/ci.yml/badge.svg?branch=master)](https://github.com/YUCONGGEN/springbootAI/actions/workflows/ci.yml)
@@ -183,7 +215,7 @@ SpringBootAI 是一个采用 Spring 风格注解和分层结构的 Python 应用
183
215
  | AI 与编排 | 模型调用、Tools、RAG、Chain、状态图、MCP client/server | LangChain / LangGraph / 官方 MCP SDK |
184
216
  | 生产治理 | 健康检查、Prometheus、限流熔断、追踪、Swagger | prometheus-client / OpenTelemetry / OpenAPI |
185
217
 
186
- 当前版本是 `2.3.2`;支持 Python 3.10、3.11 和 3.12,许可证为 MIT。项目仍标记为 Beta。用于公网高并发、合规敏感或支付/订单/库存等核心系统前,必须完成目标数据库、流量模型、故障恢复和安全基线验证。内嵌 Gateway 适合内部路由,不替代公网 Nginx/Kong/WAF;Seata `distributed` 对接官方 TC + TCC 回调;`at` 模式通过 ORM 拦截器自动生成 undo_log 实现自动回滚。
218
+ 当前版本是 `2.3.5`;支持 Python 3.10、3.11 和 3.12,许可证为 MIT。项目仍标记为 Beta。用于公网高并发、合规敏感或支付/订单/库存等核心系统前,必须完成目标数据库、流量模型、故障恢复和安全基线验证。内嵌 Gateway 适合内部路由,不替代公网 Nginx/Kong/WAF;Seata `distributed` 对接官方 TC + TCC 回调;`at` 模式通过 ORM 拦截器自动生成 undo_log 实现自动回滚。
187
219
 
188
220
  [新手指南](https://github.com/YUCONGGEN/springbootAI/blob/master/doc/BEGINNER_GUIDE.md) | [全部文档](https://github.com/YUCONGGEN/springbootAI/tree/master/doc) | [变更日志](https://github.com/YUCONGGEN/springbootAI/blob/master/CHANGELOG.md) | [安全报告](https://github.com/YUCONGGEN/springbootAI/blob/master/SECURITY.md) | [发布检查](https://github.com/YUCONGGEN/springbootAI/blob/master/doc/RELEASE_CHECKLIST.md)
189
221
 
@@ -364,10 +396,10 @@ SpringBootAI 是一个 **Python Web 框架**。它把 Java Spring Boot 的"注
364
396
 
365
397
  | 组件 | 当前版本 |
366
398
  |------|----------|
367
- | `springbootai` 框架 API | 2.3.2 |
368
- | `springbootai.orm.pymybatis` | 2.3.2 |
369
- | `springbootai.ai` AI 模块 | 2.3.2 |
370
- | `springbootai.langchain` LangChain 模块 | 2.3.2 |
399
+ | `springbootai` 框架 API | 2.3.5 |
400
+ | `springbootai.orm.pymybatis` | 2.3.5 |
401
+ | `springbootai.ai` AI 模块 | 2.3.5 |
402
+ | `springbootai.langchain` LangChain 模块 | 2.3.5 |
371
403
  | Python | 3.10+ |
372
404
 
373
405
  ### 1.4 适合什么场景
@@ -76,6 +76,7 @@ springbootai/context/__init__.py
76
76
  springbootai/context/application_context.py
77
77
  springbootai/context/bean_definition.py
78
78
  springbootai/context/bean_factory.py
79
+ springbootai/context/lifecycle.py
79
80
  springbootai/context/registry.py
80
81
  springbootai/context/scanner.py
81
82
  springbootai/core/__init__.py
@@ -268,6 +269,7 @@ tests/test_ai_module.py
268
269
  tests/test_annotation_combinations.py
269
270
  tests/test_annotations_contract.py
270
271
  tests/test_aop_annotations_full.py
272
+ tests/test_aop_pointcut_enhancements.py
271
273
  tests/test_audit_time.py
272
274
  tests/test_batch.py
273
275
  tests/test_bean_utils.py
@@ -296,6 +298,7 @@ tests/test_di_config_event_full.py
296
298
  tests/test_excel_module.py
297
299
  tests/test_hateoas.py
298
300
  tests/test_i18n_module.py
301
+ tests/test_ioc_lifecycle_enhancements.py
299
302
  tests/test_jpa_version_transient.py
300
303
  tests/test_kafka.py
301
304
  tests/test_langchain_comprehensive.py
@@ -19,7 +19,7 @@ from .config import *
19
19
  from .utils import *
20
20
  from .main import create_app, run, SpringApplication, run_cli
21
21
 
22
- __version__ = "2.3.4"
22
+ __version__ = "2.3.5"
23
23
  __author__ = "yuconggen"
24
24
  __license__ = "MIT"
25
25
 
@@ -54,7 +54,7 @@ from springbootai.ai.observability import AIMetrics, ai_metrics
54
54
  from springbootai.ai.autoconfig import AIProperties, bind_ai_config, configure_ai
55
55
  from springbootai.ai.annotation_runtime import ContentModerationError
56
56
 
57
- __version__ = "2.3.4"
57
+ __version__ = "2.3.5"
58
58
 
59
59
  __all__ = [
60
60
  # core
@@ -15,6 +15,7 @@ from .core import (
15
15
  Component,
16
16
  Aspect,
17
17
  Pointcut,
18
+ Order,
18
19
  Before,
19
20
  After,
20
21
  Around,
@@ -102,6 +103,10 @@ from .conditional import (
102
103
  ConditionalOnBean,
103
104
  ConditionalOnMissingBean,
104
105
  ConditionalOnClass,
106
+ ConditionalOnMissingClass,
107
+ ConditionalOnWebApplication,
108
+ ConditionalOnNotWebApplication,
109
+ ConditionalOnExpression,
105
110
  )
106
111
 
107
112
  # 可选导入:消息队列注解(RabbitMQ 需要 pika,Kafka 需要 kafka-python)
@@ -174,6 +179,7 @@ __all__ = [
174
179
  "Component",
175
180
  "Aspect",
176
181
  "Pointcut",
182
+ "Order",
177
183
  "Before",
178
184
  "After",
179
185
  "Around",
@@ -255,6 +261,10 @@ __all__ = [
255
261
  "ConditionalOnBean",
256
262
  "ConditionalOnMissingBean",
257
263
  "ConditionalOnClass",
264
+ "ConditionalOnMissingClass",
265
+ "ConditionalOnWebApplication",
266
+ "ConditionalOnNotWebApplication",
267
+ "ConditionalOnExpression",
258
268
  # 消息队列注解
259
269
  "RabbitListener",
260
270
  "RabbitTemplate",
@@ -238,10 +238,118 @@ class ConditionalOnClass(SpringAnnotation):
238
238
  return False
239
239
 
240
240
 
241
+ class ConditionalOnMissingClass(SpringAnnotation):
242
+ """``@ConditionalOnMissingClass``:类路径中不存在指定类时装配(对齐 Spring Boot)。"""
243
+
244
+ _annotation_type = _CONDITIONAL_TYPE
245
+
246
+ def __init__(self, name: str, value: Optional[Type] = None):
247
+ super().__init__(name=name, value=value)
248
+
249
+ def matches(self, ctx: Any) -> bool:
250
+ on_class = ConditionalOnClass(name=self.name, value=self.value)
251
+ return not on_class.matches(ctx)
252
+
253
+
254
+ class ConditionalOnWebApplication(SpringAnnotation):
255
+ """``@ConditionalOnWebApplication``:Web应用环境下装配(对齐 Spring Boot)。"""
256
+
257
+ _annotation_type = _CONDITIONAL_TYPE
258
+
259
+ def __init__(self, type: str = "any"):
260
+ """type: 'servlet' | 'reactive' | 'any'。Python框架统一为reactive(FastAPI)。"""
261
+ super().__init__(type=type)
262
+
263
+ def matches(self, ctx: Any) -> bool:
264
+ # 判断是否为Web环境:检查是否有WebApplicationContext
265
+ from springbootai.web.web_context import WebApplicationContext
266
+ return isinstance(ctx, WebApplicationContext) or hasattr(ctx, 'fastapi_app')
267
+
268
+
269
+ class ConditionalOnNotWebApplication(SpringAnnotation):
270
+ """``@ConditionalOnNotWebApplication``:非Web应用环境下装配。"""
271
+
272
+ _annotation_type = _CONDITIONAL_TYPE
273
+
274
+ def matches(self, ctx: Any) -> bool:
275
+ on_web = ConditionalOnWebApplication()
276
+ return not on_web.matches(ctx)
277
+
278
+
279
+ class ConditionalOnExpression(SpringAnnotation):
280
+ """``@ConditionalOnExpression``:基于SpEL风格表达式的条件装配。
281
+
282
+ 支持简单表达式:配置属性引用和基本布尔运算。
283
+ 语法:
284
+ "${property:default}" - 配置属性值
285
+ "true" / "false" - 布尔字面量
286
+ "property == value" - 等值比较
287
+ "!property" - 逻辑非
288
+ """
289
+
290
+ _annotation_type = _CONDITIONAL_TYPE
291
+
292
+ def __init__(self, expression: str):
293
+ super().__init__(expression=expression)
294
+
295
+ def matches(self, ctx: Any) -> bool:
296
+ loader = getattr(ctx, "config_loader", None)
297
+ expr = self.expression.strip()
298
+
299
+ # 简单布尔字面量
300
+ if expr.lower() in ("true", "false"):
301
+ return expr.lower() == "true"
302
+
303
+ # 逻辑非
304
+ if expr.startswith("!"):
305
+ inner = ConditionalOnExpression(expr[1:])
306
+ return not inner.matches(ctx)
307
+
308
+ # 属性引用 ${...}
309
+ import re
310
+ prop_match = re.match(r'^\$\{([^:}]+)(?::(.+))?\}$', expr)
311
+ if prop_match:
312
+ key = prop_match.group(1)
313
+ default = prop_match.group(2)
314
+ try:
315
+ value = loader.get(key) if loader is not None else None
316
+ except Exception:
317
+ value = None
318
+ if value is None:
319
+ value = default
320
+ return value is not None and str(value).lower() not in ("false", "0", "no", "off", "")
321
+
322
+ # 等值比较 prop == value
323
+ eq_match = re.match(r'^(.+?)\s*==\s*(.+)$', expr)
324
+ if eq_match:
325
+ left = eq_match.group(1).strip()
326
+ right = eq_match.group(2).strip().strip("'\"")
327
+ if left.startswith("${") and left.endswith("}"):
328
+ key = left[2:-1].split(":")[0]
329
+ try:
330
+ actual = loader.get(key) if loader is not None else None
331
+ except Exception:
332
+ actual = None
333
+ return str(actual) == right
334
+ return left.strip("'\"") == right
335
+
336
+ # 简单属性名:存在且不为false即装配
337
+ if expr and " " not in expr:
338
+ try:
339
+ value = loader.get(expr) if loader is not None else None
340
+ except Exception:
341
+ value = None
342
+ return value is not None and str(value).lower() not in ("false", "0", "no", "off", "")
343
+
344
+ return False
345
+
346
+
241
347
  # 供 _matches_conditions 识别的全部条件注解类型
242
348
  CONDITION_ANNOTATIONS = (
243
349
  Conditional, ConditionalOnProperty, ConditionalOnBean,
244
350
  ConditionalOnMissingBean, ConditionalOnClass,
351
+ ConditionalOnMissingClass, ConditionalOnWebApplication,
352
+ ConditionalOnNotWebApplication, ConditionalOnExpression,
245
353
  )
246
354
 
247
355
 
@@ -267,6 +375,10 @@ __all__ = [
267
375
  "ConditionalOnBean",
268
376
  "ConditionalOnMissingBean",
269
377
  "ConditionalOnClass",
378
+ "ConditionalOnMissingClass",
379
+ "ConditionalOnWebApplication",
380
+ "ConditionalOnNotWebApplication",
381
+ "ConditionalOnExpression",
270
382
  "CONDITION_ANNOTATIONS",
271
383
  "all_conditions_match",
272
384
  ]
@@ -7,7 +7,7 @@ __all__ = [
7
7
  "SpringAnnotation", "get_spring_annotations", "ApplicationEvent", "EventListener",
8
8
  "SpringBootApplication", "ComponentScan", "RestController", "Controller",
9
9
  "RequestMapping", "GetMapping", "PostMapping", "PutMapping", "PatchMapping",
10
- "DeleteMapping", "Service", "Component", "Aspect", "Pointcut", "Before",
10
+ "DeleteMapping", "Service", "Component", "Aspect", "Pointcut", "Order", "Before",
11
11
  "After", "Around", "AfterReturning", "AfterThrowing", "Repository", "Autowired",
12
12
  "Qualifier", "Configuration", "Scope", "Bean", "Value", "ConfigurationProperties",
13
13
  "RequestParam", "PathVariable", "RequestBody", "RequestPart", "FileUpload",
@@ -265,6 +265,29 @@ class Pointcut(SpringAnnotation):
265
265
  super().__init__(value=value.strip())
266
266
 
267
267
 
268
+ class Order(SpringAnnotation):
269
+ """声明组件/通知的执行优先级(对齐 Spring ``@Order``)。
270
+
271
+ 数值越小优先级越高:
272
+ - 切面通知:优先级高的 @Before 先执行、@After 后执行(对齐 Spring 语义)
273
+ - BeanPostProcessor / 拦截器:数值小的先执行
274
+
275
+ 使用示例:
276
+ @Aspect
277
+ @Order(1) # 比 @Order(2) 的通知先执行
278
+ class LoggingAspect:
279
+ ...
280
+ """
281
+
282
+ _annotation_type = "order"
283
+
284
+ def __init__(self, value: int = 0):
285
+ super().__init__(value=int(value))
286
+
287
+ def get_order(self) -> int:
288
+ return int(self.value)
289
+
290
+
268
291
  class _AdviceAnnotation:
269
292
  def _init_advice(self, value: str = "", *, pointcut: Optional[str] = None):
270
293
  expression = pointcut if pointcut is not None else value
@@ -73,6 +73,19 @@ class _AdviceDefinition:
73
73
  annotation: Any
74
74
  expression: str
75
75
  pointcuts: Dict[str, str]
76
+ order: int = 0
77
+
78
+
79
+ def _aspect_order(aspect_class: type) -> int:
80
+ """解析切面类上的 ``@Order`` 优先级(默认 0,数值越小优先级越高)。"""
81
+ for annotation in get_spring_annotations(aspect_class):
82
+ if type(annotation).__name__ == "Order":
83
+ value = getattr(annotation, "value", 0)
84
+ try:
85
+ return int(value)
86
+ except (TypeError, ValueError):
87
+ return 0
88
+ return 0
76
89
 
77
90
 
78
91
  def is_aspect_class(bean_class: type) -> bool:
@@ -118,6 +131,7 @@ def collect_advice_definitions(bean_factory: Any) -> List[_AdviceDefinition]:
118
131
  annotation=annotation,
119
132
  expression=annotation.value,
120
133
  pointcuts=pointcuts,
134
+ order=_aspect_order(aspect_class),
121
135
  )
122
136
  )
123
137
  return definitions
@@ -181,6 +195,48 @@ def _execution_pattern(expression: str) -> str:
181
195
  return parts[-1]
182
196
 
183
197
 
198
+ def _annotation_name_matches(annotation: Any, expected: str) -> bool:
199
+ """判断注解的类名(短名或全限定名)是否匹配期望名。"""
200
+ return (
201
+ type(annotation).__name__ == expected
202
+ or f"{type(annotation).__module__}.{type(annotation).__name__}" == expected
203
+ )
204
+
205
+
206
+ def _method_parameter_types(method: Callable) -> List[Any]:
207
+ """提取方法的参数类型注解(无注解的参数视为 ``object``)。"""
208
+ try:
209
+ signature = inspect.signature(method)
210
+ except (TypeError, ValueError):
211
+ return []
212
+ types_list: List[Any] = []
213
+ for parameter in signature.parameters.values():
214
+ if parameter.kind in (
215
+ inspect.Parameter.VAR_POSITIONAL,
216
+ inspect.Parameter.VAR_KEYWORD,
217
+ ):
218
+ continue
219
+ annotation = parameter.annotation
220
+ if annotation is inspect.Parameter.empty:
221
+ types_list.append(object)
222
+ else:
223
+ types_list.append(annotation)
224
+ return types_list
225
+
226
+
227
+ def _type_matches(actual: Any, expected_name: str) -> bool:
228
+ """判断类型是否匹配期望类型名(短名或全限定名)。"""
229
+ if actual is None:
230
+ actual = object
231
+ try:
232
+ if actual.__name__ == expected_name:
233
+ return True
234
+ module = getattr(actual, "__module__", "")
235
+ return f"{module}.{actual.__name__}" == expected_name
236
+ except Exception:
237
+ return False
238
+
239
+
184
240
  def _matches_atom(
185
241
  expression: str,
186
242
  *,
@@ -227,10 +283,55 @@ def _matches_atom(
227
283
  if not expected:
228
284
  raise ValueError("@annotation pointcut must include an annotation name")
229
285
  return any(
230
- type(annotation).__name__ == expected
231
- or f"{type(annotation).__module__}.{type(annotation).__name__}" == expected
286
+ _annotation_name_matches(annotation, expected)
232
287
  for annotation in get_spring_annotations(method)
233
288
  )
289
+ if expression.startswith("@within(") and expression.endswith(")"):
290
+ expected = expression[len("@within("):-1].strip()
291
+ if not expected:
292
+ raise ValueError("@within pointcut must include an annotation name")
293
+ return any(
294
+ _annotation_name_matches(annotation, expected)
295
+ for annotation in get_spring_annotations(target_class)
296
+ )
297
+ if expression.startswith("@target(") and expression.endswith(")"):
298
+ expected = expression[len("@target("):-1].strip()
299
+ if not expected:
300
+ raise ValueError("@target pointcut must include an annotation name")
301
+ return any(
302
+ _annotation_name_matches(annotation, expected)
303
+ for annotation in get_spring_annotations(target_class)
304
+ )
305
+ if expression.startswith("args(") and expression.endswith(")"):
306
+ inner = expression[len("args("):-1].strip()
307
+ if not inner:
308
+ raise ValueError("args pointcut must include parameter types")
309
+ expected_types = [part.strip() for part in inner.split(",") if part.strip()]
310
+ actual_types = _method_parameter_types(method)
311
+ # 无类型约束时(空签名)不匹配任何 args 表达式
312
+ if not actual_types:
313
+ return False
314
+ # 参数数量必须一致(或用 .. 表示任意前缀,简化为前缀匹配)
315
+ if len(expected_types) != len(actual_types):
316
+ return False
317
+ return all(
318
+ _type_matches(actual, expected)
319
+ for actual, expected in zip(actual_types, expected_types)
320
+ )
321
+ if expression.startswith("@args(") and expression.endswith(")"):
322
+ expected = expression[len("@args("):-1].strip()
323
+ if not expected:
324
+ raise ValueError("@args pointcut must include an annotation name")
325
+ # 匹配方法参数上是否带有指定注解
326
+ try:
327
+ signature = inspect.signature(method)
328
+ except (TypeError, ValueError):
329
+ return False
330
+ for parameter in signature.parameters.values():
331
+ for annotation in get_spring_annotations(parameter.annotation) if isinstance(parameter.annotation, type) else []:
332
+ if _annotation_name_matches(annotation, expected):
333
+ return True
334
+ return False
234
335
  raise ValueError(f"Unsupported pointcut expression: {expression}")
235
336
 
236
337
 
@@ -395,6 +496,14 @@ def apply_aspects(
395
496
  item for item in advice if type(item.annotation) is AfterThrowing
396
497
  ]
397
498
 
499
+ # @Order 优先级:before/around 按 order 升序(值小先执行);
500
+ # after/after_returning/after_throwing 按 order 降序(值大先执行),形成"洋葱"结构。
501
+ before.sort(key=lambda item: item.order)
502
+ around.sort(key=lambda item: item.order)
503
+ after.sort(key=lambda item: item.order, reverse=True)
504
+ after_returning.sort(key=lambda item: item.order, reverse=True)
505
+ after_throwing.sort(key=lambda item: item.order, reverse=True)
506
+
398
507
  def business_args(call_args):
399
508
  if call_args and call_args[0] is target:
400
509
  return call_args[1:]