搜索 K
Appearance
Appearance
注解写好后,元数据全部存活在 ModelRegistry 里 —— 后续无论是生成 SQL、给前端低代码渲染表单、还是写运维巡检脚本,都是从这里拿数据。本章给出编程式访问元数据的最小示例,并附核心类速查表便于回查方法签名。
ModelRegistry 是普通 Spring Bean,注入即可使用:
import cn.cvking.forge.ddl.model.FieldDefinition;
import cn.cvking.forge.ddl.model.ModelDefinition;
import cn.cvking.forge.ddl.registry.ModelRegistry;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
import java.util.Collection;
@RestController
@RequiredArgsConstructor
public class MetadataInspectorController {
private final ModelRegistry registry;
/** 列出全部已注册模型 */
@GetMapping("/_meta/models")
public Collection<ModelDefinition> all() {
return registry.getAllModels();
}
/** 按 modelName 查单个模型 */
@GetMapping("/_meta/models/{name}")
public ModelDefinition byName(@PathVariable String name) {
return registry.getModel(name);
}
}启动后访问 GET /_meta/models 即可得到形如:
[
{
"modelName": "user",
"tableName": "user",
"modelType": "STORE",
"displayName": "用户",
"fields": [
{ "fieldName": "name", "columnName": "user_name",
"javaType": "java.lang.String", "fieldType": "STRING",
"length": 64, "nullable": true, "store": true }
]
}
]ModelDefinition 与 FieldDefinition 都是 @Data @Builder POJO + 实现 Serializable,Jackson 可直接序列化。
典型用途
store=true 的字段,检查是否在数据库已建表所有类位于 cn.cvking.forge.ddl 包及其子包。
DdlAutoConfiguration 包:cn.cvking.forge.ddl
@AutoConfiguration
@ComponentScan(basePackageClasses = DdlAutoConfiguration.class)
public class DdlAutoConfiguration {}自动装配入口,通过 META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports 注册到 Spring Boot。详细机制见 前置知识 · Spring Boot 自动装配。
DdlInitializer 包:cn.cvking.forge.ddl.runner。implements ApplicationRunner,由 Spring Boot 在启动尾部自动触发。
| 方法 | 签名 | 用途 |
|---|---|---|
run | void run(ApplicationArguments args) | 主流程入口:取扫描包 → 扫描 → 解析 → 注册 |
fetchScanPackages | private String[] fetchScanPackages() | 通过 AutoConfigurationPackages.get(beanFactory) 取扫描根 |
parseModel | private ModelDefinition parseModel(Class<?>) | 把类解析为 ModelDefinition |
parseFields | private List<FieldDefinition> parseFields(Class<?>) | 遍历声明字段,跳过 static |
buildFieldDefinition | private FieldDefinition buildFieldDefinition(Field) | 单字段转换;无相关注解时返回 null |
inferTypeFromJavaType | private FieldType inferTypeFromJavaType(Field) | Java 类型兜底推导;未命中抛 IllegalStateException |
fillTypeAttributes | private void fillTypeAttributes(...) | 按字段类型填充 length / precision / scale / dateType |
构造期注入 ClazzScanner / ModelRegistry / BeanFactory。
ClazzScanner 包:cn.cvking.forge.ddl.scanner
| 方法 | 签名 | 用途 |
|---|---|---|
scan | Set<Class<?>> scan(String... packages) | 扫描指定包路径下所有 @Model 类;返回保持扫描顺序的 LinkedHashSet |
buildProvider | private ClassPathScanningCandidateComponentProvider buildProvider() | 构造扫描器:关闭默认 filter、加 @AnnotationTypeFilter(Model.class)、排除内部类 |
isUnsupportedClass | private boolean isUnsupportedClass(Class<?>) | 反射兜底过滤:成员/匿名/局部/抽象/接口 |
底层使用 ClassPathScanningCandidateComponentProvider,详见 前置知识 · Spring 包扫描。
ModelRegistry 包:cn.cvking.forge.ddl.registry
private final Map<String, ModelDefinition> registry = new ConcurrentHashMap<>();| 方法 | 签名 | 行为 |
|---|---|---|
register | void register(ModelDefinition definition) | 注册;null 或 modelName == null 抛 IllegalArgumentException;重名 WARN + 覆盖 |
getModel | ModelDefinition getModel(String modelName) | 单查询,未命中返回 null |
getAllModels | Collection<ModelDefinition> getAllModels() | 返回 Collections.unmodifiableCollection(registry.values()) |
详细策略与并发选型见 设计文档 · 模型注册中心。
ModelDefinition 包:cn.cvking.forge.ddl.model,@Data @Builder,实现 Serializable。
| 字段 | 类型 | 说明 |
|---|---|---|
modelName | String | 模型唯一标识 |
tableName | String | 数据库表名 |
modelType | ModelTypeEnum | 模型类型 |
displayName | String | 展示名 |
summary | String | 描述摘要 |
sourceClass | Class<?> | 原始 Class(@ToString.Exclude) |
fields | List<FieldDefinition> | 字段定义列表 |
FieldDefinition 包:cn.cvking.forge.ddl.model,@Data @Builder,实现 Serializable。
| 字段 | 类型 | 说明 |
|---|---|---|
fieldName | String | Java 字段名 |
columnName | String | 数据库列名 |
javaType | Class<?> | Java 类型 |
fieldType | FieldType | 业务字段类型 |
length | Integer | 字符串长度(仅 STRING) |
precision | Integer | 总位数(仅 BIG_DECIMAL) |
scale | Integer | 小数位(仅 BIG_DECIMAL) |
dateType | DateType | 日期语义(仅 DATE) |
nullable | Boolean | 是否可空(基本类型 false,包装/引用类型 true) |
store | Boolean | 是否持久化(来自 @Field.Advanced.store) |
NamingUtils 包:cn.cvking.forge.ddl.utils,工具类(final,私有构造)。
| 静态方法 | 签名 | 用途 |
|---|---|---|
computeTableName | String computeTableName(Model.Advanced advanced, String modelName) | 优先用 @Model.Advanced.table;否则 camelToUnderscore(modelName) |
resolveColumnName | String resolveColumnName(Field.Advanced advanced, String fieldName) | 优先用 @Field.Advanced.column;否则 camelToUnderscore(fieldName) |
camelToUnderscore | String camelToUnderscore(String name) | 驼峰转下划线小写 |
FieldTypeHelper 包:cn.cvking.forge.ddl.utils,工具类。
| 静态方法 | 签名 | 用途 |
|---|---|---|
findByAnnotation | FieldType findByAnnotation(Field reflectField) | 按字段上的类型子注解查 FieldType;未命中返回 null |
findByJavaType | FieldType findByJavaType(Class<?> javaType) | 按 Java 类型查 FieldType;未命中返回 null |
内部维护两张静态 Map:
ANNOTATION_TO_TYPE:8 个类型子注解 → FieldTypeJAVA_TYPE_TO_TYPE:14 种 Java 类型 → FieldType(含基本类型与包装类型)详见 设计文档 · 类型推导。