springbootAI 1.8.0__py3-none-any.whl
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.
- spring/__init__.py +66 -0
- spring/ai/__init__.py +78 -0
- spring/ai/advisors.py +139 -0
- spring/ai/annotations.py +74 -0
- spring/ai/autoconfig.py +481 -0
- spring/ai/core.py +391 -0
- spring/ai/etl.py +188 -0
- spring/ai/memory.py +109 -0
- spring/ai/observability.py +129 -0
- spring/ai/providers.py +789 -0
- spring/ai/resilience.py +258 -0
- spring/ai/tools.py +106 -0
- spring/ai/vectorstore.py +303 -0
- spring/annotations/__init__.py +188 -0
- spring/annotations/cache.py +126 -0
- spring/annotations/cloud.py +207 -0
- spring/annotations/conditional.py +272 -0
- spring/annotations/core.py +864 -0
- spring/annotations/messaging.py +107 -0
- spring/aop/__init__.py +4 -0
- spring/aop/cloud_aop.py +404 -0
- spring/aop/comprehensive_aop.py +1015 -0
- spring/aop/method_interceptor.py +19 -0
- spring/aop/proxy_factory.py +55 -0
- spring/cloud/__init__.py +76 -0
- spring/cloud/discovery.py +364 -0
- spring/cloud/feign.py +469 -0
- spring/cloud/gateway.py +452 -0
- spring/cloud/load_balancer.py +149 -0
- spring/cloud/seata.py +557 -0
- spring/cloud/sentinel.py +525 -0
- spring/cloud/tracer.py +337 -0
- spring/config/__init__.py +21 -0
- spring/config/binding.py +206 -0
- spring/config/config_loader.py +405 -0
- spring/context/__init__.py +13 -0
- spring/context/application_context.py +589 -0
- spring/context/bean_definition.py +70 -0
- spring/context/bean_factory.py +1052 -0
- spring/context/registry.py +58 -0
- spring/context/scanner.py +106 -0
- spring/core/__init__.py +3 -0
- spring/core/graceful_shutdown.py +196 -0
- spring/core/typing_utils.py +50 -0
- spring/csv/__init__.py +52 -0
- spring/csv/annotations.py +402 -0
- spring/csv/converters.py +69 -0
- spring/csv/easy_csv.py +95 -0
- spring/csv/exceptions.py +27 -0
- spring/csv/reader.py +195 -0
- spring/csv/writer.py +155 -0
- spring/data/__init__.py +54 -0
- spring/data/page.py +181 -0
- spring/data/repository.py +274 -0
- spring/data/specification.py +228 -0
- spring/datasource/__init__.py +66 -0
- spring/datasource/annotations.py +133 -0
- spring/datasource/context.py +69 -0
- spring/datasource/dynamic.py +148 -0
- spring/event/__init__.py +7 -0
- spring/event/publisher.py +69 -0
- spring/excel/__init__.py +51 -0
- spring/excel/annotations.py +405 -0
- spring/excel/converters.py +231 -0
- spring/excel/easy_excel.py +94 -0
- spring/excel/exceptions.py +31 -0
- spring/excel/reader.py +254 -0
- spring/excel/style.py +95 -0
- spring/excel/writer.py +197 -0
- spring/i18n/__init__.py +97 -0
- spring/i18n/accessor.py +94 -0
- spring/i18n/auto_config.py +177 -0
- spring/i18n/holder.py +106 -0
- spring/i18n/locale.py +152 -0
- spring/i18n/locale_resolver.py +367 -0
- spring/i18n/message_source.py +250 -0
- spring/i18n/middleware.py +79 -0
- spring/i18n/properties.py +168 -0
- spring/i18n/sources.py +255 -0
- spring/logging/__init__.py +1 -0
- spring/logging/loguru_logger.py +228 -0
- spring/main.py +378 -0
- spring/messaging/__init__.py +1 -0
- spring/messaging/rabbitmq.py +302 -0
- spring/monitoring/__init__.py +1 -0
- spring/monitoring/prometheus.py +199 -0
- spring/orm/__init__.py +258 -0
- spring/orm/database.py +222 -0
- spring/orm/ddl_auto.py +1217 -0
- spring/orm/migration.py +419 -0
- spring/orm/mybatis_integration.py +400 -0
- spring/orm/pymybatis/__init__.py +86 -0
- spring/orm/pymybatis/annotations/__init__.py +30 -0
- spring/orm/pymybatis/annotations/annotations.py +332 -0
- spring/orm/pymybatis/cache/__init__.py +47 -0
- spring/orm/pymybatis/cache/cache.py +371 -0
- spring/orm/pymybatis/cache/redis_cache.py +434 -0
- spring/orm/pymybatis/circuit_breaker/__init__.py +21 -0
- spring/orm/pymybatis/circuit_breaker/circuit_breaker.py +424 -0
- spring/orm/pymybatis/configuration.py +525 -0
- spring/orm/pymybatis/core/__init__.py +10 -0
- spring/orm/pymybatis/core/sql_session.py +1382 -0
- spring/orm/pymybatis/core/sql_session_factory.py +76 -0
- spring/orm/pymybatis/dialect/__init__.py +9 -0
- spring/orm/pymybatis/dialect/dialect.py +445 -0
- spring/orm/pymybatis/dynamic_sql/__init__.py +9 -0
- spring/orm/pymybatis/dynamic_sql/dynamic_sql.py +900 -0
- spring/orm/pymybatis/interceptor/__init__.py +31 -0
- spring/orm/pymybatis/interceptor/interceptor.py +427 -0
- spring/orm/pymybatis/mapper/__init__.py +9 -0
- spring/orm/pymybatis/mapper/mapper.py +540 -0
- spring/orm/pymybatis/metrics/__init__.py +41 -0
- spring/orm/pymybatis/metrics/metrics.py +595 -0
- spring/orm/pymybatis/pool/__init__.py +9 -0
- spring/orm/pymybatis/pool/connection_pool.py +711 -0
- spring/orm/pymybatis/security/__init__.py +19 -0
- spring/orm/pymybatis/security/access_control.py +415 -0
- spring/orm/pymybatis/security/password_encoder.py +293 -0
- spring/orm/pymybatis/security/sensitive_data_masker.py +326 -0
- spring/orm/pymybatis/security/sql_injection_detector.py +675 -0
- spring/orm/pymybatis/transaction/__init__.py +9 -0
- spring/orm/pymybatis/transaction/transaction.py +288 -0
- spring/orm/pymybatis/type_handler/__init__.py +37 -0
- spring/orm/pymybatis/type_handler/type_handler.py +473 -0
- spring/orm/pymybatis/version.py +9 -0
- spring/orm/pymybatis/xml_parser/__init__.py +9 -0
- spring/orm/pymybatis/xml_parser/xml_parser.py +761 -0
- spring/retry/__init__.py +12 -0
- spring/retry/retry_annotations.py +71 -0
- spring/retry/retry_decorator.py +155 -0
- spring/scheduling/__init__.py +3 -0
- spring/scheduling/scheduler.py +389 -0
- spring/security/__init__.py +39 -0
- spring/security/jwt_utils.py +281 -0
- spring/security/replay_protection.py +206 -0
- spring/security/secret_manager.py +226 -0
- spring/security/security_aop.py +248 -0
- spring/security/security_context.py +172 -0
- spring/test/__init__.py +45 -0
- spring/test/slicing.py +341 -0
- spring/tracing/__init__.py +11 -0
- spring/tracing/skywalking.py +229 -0
- spring/tx/__init__.py +52 -0
- spring/tx/events.py +172 -0
- spring/tx/synchronization.py +143 -0
- spring/utils/__init__.py +5 -0
- spring/utils/banner.py +32 -0
- spring/utils/logger.py +73 -0
- spring/utils/redis_client.py +526 -0
- spring/validation/__init__.py +55 -0
- spring/validation/aop.py +141 -0
- spring/validation/constraints.py +357 -0
- spring/validation/exceptions.py +55 -0
- spring/validation/validator.py +139 -0
- spring/web/__init__.py +12 -0
- spring/web/actuator.py +319 -0
- spring/web/exception_handler.py +61 -0
- spring/web/health.py +399 -0
- spring/web/interceptor.py +91 -0
- spring/web/result.py +44 -0
- spring/web/swagger.py +601 -0
- spring/web/web_context.py +755 -0
- spring/websocket/__init__.py +86 -0
- spring/websocket/annotations.py +169 -0
- spring/websocket/broker.py +238 -0
- spring/websocket/exceptions.py +26 -0
- spring/websocket/handler.py +243 -0
- spring/websocket/router.py +526 -0
- spring/websocket/session.py +216 -0
- springbootai-1.8.0.dist-info/METADATA +2796 -0
- springbootai-1.8.0.dist-info/RECORD +175 -0
- springbootai-1.8.0.dist-info/WHEEL +5 -0
- springbootai-1.8.0.dist-info/entry_points.txt +2 -0
- springbootai-1.8.0.dist-info/licenses/LICENSE +7 -0
- springbootai-1.8.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,272 @@
|
|
|
1
|
+
"""SpringBootAI 条件装配注解 —— 对齐 Spring Boot 的条件化 Bean 注册。
|
|
2
|
+
|
|
3
|
+
本模块在既有 ``@Profile``(``spring.annotations.core.Profile``)基础上补齐 Spring Boot
|
|
4
|
+
条件装配家族,复用同一 ``SpringAnnotation`` 元数据范式:
|
|
5
|
+
|
|
6
|
+
- ``@Conditional``:自定义条件(传入 ``Condition`` 子类实例或 ``callable(context)->bool``)。
|
|
7
|
+
- ``@ConditionalOnProperty``:配置属性匹配时装配。
|
|
8
|
+
- ``@ConditionalOnBean``:容器中已存在指定 Bean 时装配。
|
|
9
|
+
- ``@ConditionalOnMissingBean``:容器中不存在指定 Bean 时装配。
|
|
10
|
+
- ``@ConditionalOnClass``:类路径中存在指定类时装配。
|
|
11
|
+
|
|
12
|
+
每个注解实现 ``matches(application_context) -> bool``,由
|
|
13
|
+
``ApplicationContext._matches_conditions`` 在 ``_register_component`` 阶段统一求值
|
|
14
|
+
(与既有 ``_matches_active_profile`` 并列)。
|
|
15
|
+
|
|
16
|
+
与 Spring 的一致点:
|
|
17
|
+
- 条件求值时机:组件扫描注册阶段(BeanDefinition 注册前)。
|
|
18
|
+
- ``@ConditionalOnProperty`` 的 ``having_value`` / ``match_if_missing`` 语义对齐 Spring。
|
|
19
|
+
- ``@Conditional`` 支持传入 ``Condition`` 类(实现 ``matches(context)``)。
|
|
20
|
+
|
|
21
|
+
与 Spring 的差异(已标注):
|
|
22
|
+
- Spring 条件求值访问 ``ConditionContext`` + ``AnnotatedTypeMetadata``;本框架传入
|
|
23
|
+
``ApplicationContext`` 本身(含 ``config_loader`` / ``bean_factory``),简化但等价。
|
|
24
|
+
- ``@ConditionalOnBean`` / ``@ConditionalOnMissingBean`` 检查的是**已注册的
|
|
25
|
+
BeanDefinition 名字/类型**,而非已实例化的 Bean(与 Spring 一致),但受扫描顺序影响:
|
|
26
|
+
若依赖的 Bean 在当前组件之后扫描,则条件求值为假。生产中应把被依赖 Bean 放在更早的包
|
|
27
|
+
或用 ``@Configuration`` + ``@Bean`` 显式声明(这是已知限制,对齐 Spring 的注册顺序敏感性)。
|
|
28
|
+
- 不支持 SpEL;``having_value`` 为字符串等值匹配。
|
|
29
|
+
"""
|
|
30
|
+
from __future__ import annotations
|
|
31
|
+
|
|
32
|
+
import importlib
|
|
33
|
+
from typing import Any, Optional, Type, Union
|
|
34
|
+
|
|
35
|
+
from spring.annotations.core import SpringAnnotation
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
# 条件注解类型标识,便于 _matches_conditions 用 _annotation_type 批量识别
|
|
39
|
+
_CONDITIONAL_TYPE = "conditional"
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
class Conditional(SpringAnnotation):
|
|
43
|
+
"""``@Conditional``:自定义条件装配(对齐 Spring ``@Conditional``)。
|
|
44
|
+
|
|
45
|
+
Args:
|
|
46
|
+
condition: 条件。可为:
|
|
47
|
+
- ``Condition`` 子类**类型**(会实例化后调用 ``matches(context)``);
|
|
48
|
+
- ``Condition`` 子类**实例**(直接调用 ``matches(context)``);
|
|
49
|
+
- ``callable(context) -> bool``(直接调用)。
|
|
50
|
+
"""
|
|
51
|
+
|
|
52
|
+
_annotation_type = _CONDITIONAL_TYPE
|
|
53
|
+
|
|
54
|
+
def __new__(cls, *args, **kwargs):
|
|
55
|
+
# ``Conditional`` 的第一个位置参数是 condition(类或可调用),并非被装饰目标。
|
|
56
|
+
# 跳过 ``SpringAnnotation.__new__`` 的"无括号装饰器"优化,避免把 condition 误判
|
|
57
|
+
# 为装饰目标(否则 ``Conditional(MyCond)`` 会被当成 ``@Conditional`` 作用于 MyCond)。
|
|
58
|
+
return super().__new__(cls)
|
|
59
|
+
|
|
60
|
+
def __init__(self, condition: Union[Type, Any, callable]):
|
|
61
|
+
super().__init__(condition=condition)
|
|
62
|
+
|
|
63
|
+
def matches(self, ctx: Any) -> bool:
|
|
64
|
+
cond = self.condition
|
|
65
|
+
# 传入的是类 -> 实例化
|
|
66
|
+
if isinstance(cond, type):
|
|
67
|
+
try:
|
|
68
|
+
inst = cond()
|
|
69
|
+
except Exception:
|
|
70
|
+
return False
|
|
71
|
+
else:
|
|
72
|
+
inst = cond
|
|
73
|
+
if hasattr(inst, "matches") and callable(inst.matches):
|
|
74
|
+
try:
|
|
75
|
+
return bool(inst.matches(ctx))
|
|
76
|
+
except Exception:
|
|
77
|
+
return False
|
|
78
|
+
if callable(inst):
|
|
79
|
+
try:
|
|
80
|
+
return bool(inst(ctx))
|
|
81
|
+
except Exception:
|
|
82
|
+
return False
|
|
83
|
+
return True
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
class ConditionalOnProperty(SpringAnnotation):
|
|
87
|
+
"""``@ConditionalOnProperty``:配置属性匹配时装配(对齐 Spring Boot)。
|
|
88
|
+
|
|
89
|
+
Args:
|
|
90
|
+
name: 配置键(如 ``"redis.enabled"``)。
|
|
91
|
+
having_value: 期望值(字符串等值匹配)。为 None 时只要键存在(非 None)即匹配。
|
|
92
|
+
match_if_missing: 配置键缺失时是否视为匹配。默认 False。
|
|
93
|
+
"""
|
|
94
|
+
|
|
95
|
+
_annotation_type = _CONDITIONAL_TYPE
|
|
96
|
+
|
|
97
|
+
def __init__(
|
|
98
|
+
self,
|
|
99
|
+
name: str,
|
|
100
|
+
having_value: Optional[str] = None,
|
|
101
|
+
match_if_missing: bool = False,
|
|
102
|
+
):
|
|
103
|
+
super().__init__(name=name, having_value=having_value, match_if_missing=match_if_missing)
|
|
104
|
+
|
|
105
|
+
def matches(self, ctx: Any) -> bool:
|
|
106
|
+
loader = getattr(ctx, "config_loader", None)
|
|
107
|
+
try:
|
|
108
|
+
value = loader.get(self.name) if loader is not None else None
|
|
109
|
+
except Exception:
|
|
110
|
+
value = None
|
|
111
|
+
if value is None:
|
|
112
|
+
return bool(self.match_if_missing)
|
|
113
|
+
if self.having_value is None:
|
|
114
|
+
return True
|
|
115
|
+
return str(value) == str(self.having_value)
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
class ConditionalOnBean(SpringAnnotation):
|
|
119
|
+
"""``@ConditionalOnBean``:容器中已存在指定 Bean 时装配(对齐 Spring Boot)。
|
|
120
|
+
|
|
121
|
+
Args:
|
|
122
|
+
bean_name: Bean 名称。
|
|
123
|
+
bean_type: Bean 类型(按类型匹配,会查 BeanDefinition 的 bean_class)。
|
|
124
|
+
value: bean_name 的别名(对齐 Spring 参数风格)。
|
|
125
|
+
"""
|
|
126
|
+
|
|
127
|
+
_annotation_type = _CONDITIONAL_TYPE
|
|
128
|
+
|
|
129
|
+
def __init__(
|
|
130
|
+
self,
|
|
131
|
+
bean_name: Optional[str] = None,
|
|
132
|
+
bean_type: Optional[Type] = None,
|
|
133
|
+
value: Optional[str] = None,
|
|
134
|
+
):
|
|
135
|
+
if value is not None and bean_name is None:
|
|
136
|
+
bean_name = value
|
|
137
|
+
super().__init__(bean_name=bean_name, bean_type=bean_type, value=value)
|
|
138
|
+
|
|
139
|
+
def matches(self, ctx: Any) -> bool:
|
|
140
|
+
bf = getattr(ctx, "bean_factory", None)
|
|
141
|
+
if bf is None:
|
|
142
|
+
return False
|
|
143
|
+
try:
|
|
144
|
+
names = bf.get_bean_names()
|
|
145
|
+
except Exception:
|
|
146
|
+
return False
|
|
147
|
+
if self.bean_name:
|
|
148
|
+
if self.bean_name in names:
|
|
149
|
+
return True
|
|
150
|
+
if self.bean_type is not None:
|
|
151
|
+
# 按类型匹配:遍历 BeanDefinition 的 bean_class
|
|
152
|
+
try:
|
|
153
|
+
for name in names:
|
|
154
|
+
defn = bf._bean_definitions.get(name)
|
|
155
|
+
if defn is not None and getattr(defn, "bean_class", None) is self.bean_type:
|
|
156
|
+
return True
|
|
157
|
+
if defn is not None and isinstance(getattr(defn, "bean_class", None), type):
|
|
158
|
+
if issubclass(defn.bean_class, self.bean_type):
|
|
159
|
+
return True
|
|
160
|
+
except Exception:
|
|
161
|
+
return False
|
|
162
|
+
return False
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
class ConditionalOnMissingBean(SpringAnnotation):
|
|
166
|
+
"""``@ConditionalOnMissingBean``:容器中不存在指定 Bean 时装配(对齐 Spring Boot)。
|
|
167
|
+
|
|
168
|
+
参数同 ``@ConditionalOnBean``。常用于提供默认实现:用户未自定义时装配默认 Bean。
|
|
169
|
+
"""
|
|
170
|
+
|
|
171
|
+
_annotation_type = _CONDITIONAL_TYPE
|
|
172
|
+
|
|
173
|
+
def __init__(
|
|
174
|
+
self,
|
|
175
|
+
bean_name: Optional[str] = None,
|
|
176
|
+
bean_type: Optional[Type] = None,
|
|
177
|
+
value: Optional[str] = None,
|
|
178
|
+
):
|
|
179
|
+
if value is not None and bean_name is None:
|
|
180
|
+
bean_name = value
|
|
181
|
+
super().__init__(bean_name=bean_name, bean_type=bean_type, value=value)
|
|
182
|
+
|
|
183
|
+
def matches(self, ctx: Any) -> bool:
|
|
184
|
+
on_bean = ConditionalOnBean(
|
|
185
|
+
bean_name=self.bean_name, bean_type=self.bean_type, value=self.value)
|
|
186
|
+
return not on_bean.matches(ctx)
|
|
187
|
+
|
|
188
|
+
|
|
189
|
+
class ConditionalOnClass(SpringAnnotation):
|
|
190
|
+
"""``@ConditionalOnClass``:类路径中存在指定类时装配(对齐 Spring Boot)。
|
|
191
|
+
|
|
192
|
+
Args:
|
|
193
|
+
name: 类的全限定名(``"module.Class"``)或模块名(``"module"``)。
|
|
194
|
+
value: 类类型本身(直接判断,等价于 ``isinstance`` 可导入)。
|
|
195
|
+
"""
|
|
196
|
+
|
|
197
|
+
_annotation_type = _CONDITIONAL_TYPE
|
|
198
|
+
|
|
199
|
+
def __init__(
|
|
200
|
+
self,
|
|
201
|
+
name: Optional[str] = None,
|
|
202
|
+
value: Optional[Type] = None,
|
|
203
|
+
):
|
|
204
|
+
super().__init__(name=name, value=value)
|
|
205
|
+
|
|
206
|
+
def matches(self, ctx: Any) -> bool:
|
|
207
|
+
# 直接传类类型
|
|
208
|
+
if self.value is not None:
|
|
209
|
+
return isinstance(self.value, type)
|
|
210
|
+
if not self.name:
|
|
211
|
+
return False
|
|
212
|
+
target = self.name
|
|
213
|
+
# 支持 "module.Sub.Class" 形式:从左到右尝试 import
|
|
214
|
+
parts = target.split(".")
|
|
215
|
+
# 先尝试整体作为模块
|
|
216
|
+
try:
|
|
217
|
+
importlib.import_module(target)
|
|
218
|
+
return True
|
|
219
|
+
except ImportError:
|
|
220
|
+
pass
|
|
221
|
+
# 尝试 module + attr
|
|
222
|
+
for i in range(len(parts) - 1, 0, -1):
|
|
223
|
+
mod_path = ".".join(parts[:i])
|
|
224
|
+
attr_path = parts[i:]
|
|
225
|
+
try:
|
|
226
|
+
mod = importlib.import_module(mod_path)
|
|
227
|
+
except ImportError:
|
|
228
|
+
continue
|
|
229
|
+
obj = mod
|
|
230
|
+
ok = True
|
|
231
|
+
for attr in attr_path:
|
|
232
|
+
if not hasattr(obj, attr):
|
|
233
|
+
ok = False
|
|
234
|
+
break
|
|
235
|
+
obj = getattr(obj, attr)
|
|
236
|
+
if ok:
|
|
237
|
+
return True
|
|
238
|
+
return False
|
|
239
|
+
|
|
240
|
+
|
|
241
|
+
# 供 _matches_conditions 识别的全部条件注解类型
|
|
242
|
+
CONDITION_ANNOTATIONS = (
|
|
243
|
+
Conditional, ConditionalOnProperty, ConditionalOnBean,
|
|
244
|
+
ConditionalOnMissingBean, ConditionalOnClass,
|
|
245
|
+
)
|
|
246
|
+
|
|
247
|
+
|
|
248
|
+
def all_conditions_match(component_class: type, ctx: Any) -> bool:
|
|
249
|
+
"""求类上所有条件注解的合取(AND)。任一条件为假则返回 False。
|
|
250
|
+
|
|
251
|
+
供 ``ApplicationContext._matches_conditions`` 调用,集中条件求值逻辑。
|
|
252
|
+
"""
|
|
253
|
+
from spring.annotations.core import get_spring_annotations
|
|
254
|
+
for ann in get_spring_annotations(component_class):
|
|
255
|
+
if isinstance(ann, CONDITION_ANNOTATIONS):
|
|
256
|
+
try:
|
|
257
|
+
if not ann.matches(ctx):
|
|
258
|
+
return False
|
|
259
|
+
except Exception:
|
|
260
|
+
return False
|
|
261
|
+
return True
|
|
262
|
+
|
|
263
|
+
|
|
264
|
+
__all__ = [
|
|
265
|
+
"Conditional",
|
|
266
|
+
"ConditionalOnProperty",
|
|
267
|
+
"ConditionalOnBean",
|
|
268
|
+
"ConditionalOnMissingBean",
|
|
269
|
+
"ConditionalOnClass",
|
|
270
|
+
"CONDITION_ANNOTATIONS",
|
|
271
|
+
"all_conditions_match",
|
|
272
|
+
]
|