
EggG 通过 Handler 机制将注解解析逻辑集中管理。注册 Handler 后，元数据创建时会自动调用，结果随元数据一起缓存。

### 1、问题场景

假设你在开发一个 JSON 序列化框架，用户类如下：

```java
public class User {
    @ONodeAttr(alias = "user_name")
    private String userName;

    @ONodeAttr(alias = "created_at")
    private Date createdAt;
}
```

需要把 `userName` 字段序列化为 `"user_name"`。传统做法是在每个使用点写 `if-else` + `getAnnotation()`：

```java
ONodeAttr attr = field.getAnnotation(ONodeAttr.class);
String alias = (attr != null) ? attr.alias() : field.getName();
```

字段和注解类型一多，逻辑就散落在各处，维护成本上升。类似的问题也出现在依赖注入（读 `@Inject`）、ORM（读 `@Column`）等场景。

EggG 通过 **DigestHandler** 和 **AliasHandler** 将这个逻辑统一收拢：编写一次解析规则，所有元数据自动处理。

### 2、Handler 体系

#### DigestHandler — 提炼处理器

`DigestHandler` 是一个函数式接口，在元数据创建时自动调用，从注解中提炼出自定义信息：

```java
@FunctionalInterface
public interface DigestHandler {
    Object apply(ClassEggg classEggg, AnnotatedEggg source, Object defaultValue);
}
```

参数说明：
- `classEggg`：当前类的元数据（提供类级别上下文）
- `source`：当前正在处理的注解元素，可能是 FieldEggg、MethodEggg、ParamEggg 等
- `defaultValue`：默认值（通常为 null）

返回值是提炼出的自定义对象，后续通过 `source.getDigest()` 获取。

#### AliasHandler — 别名处理器

`AliasHandler` 是函数式接口，用于为字段、参数、属性生成别名：

```java
@FunctionalInterface
public interface AliasHandler {
    String apply(ClassEggg classEggg, AnnotatedEggg source, String defaultValue);
}
```

参数说明：
- `classEggg`：当前类的元数据
- `source`：当前正在处理的注解元素
- `defaultValue`：默认别名（通常是字段/参数的原始名称）

返回值是最终的别名。注解没有指定别名时返回 `defaultValue`，有指定时返回注解中的值。

### 3、注册 Handler

在创建 Eggg 实例时通过 `withXxxHandler` 方法注册：

```java
Eggg eggg = new Eggg()
    .withDigestHandler(this::doDigestHandle)
    .withAliasHandler(this::doAliasHandle)
    .withReflectHandler(new CustomReflectHandler());
```

注册后，每次创建 FieldEggg、MethodEggg、ParamEggg 等元数据时，Handler 会自动被调用，结果直接缓存。

### 4、实战：Snack4 集成示例

以下代码展示了在 JSON 库 Snack4 中，用 EggG 统一处理 `@ONodeAttr` 注解：

```java
public class EgggUtil {
    private static final Eggg eggg = new Eggg()
            .withCreatorClass(ONodeCreator.class)
            .withDigestHandler(EgggUtil::doDigestHandle)
            .withAliasHandler(EgggUtil::doAliasHandle);

    /**
     * 别名处理器：从 Digest 中提取别名
     */
    private static String doAliasHandle(ClassEggg cw, AnnotatedEggg s, String ref) {
        if (s.getDigest() instanceof ONodeAttrHolder) {
            return ((ONodeAttrHolder) s.getDigest()).getAlias();
        } else {
            return ref;
        }
    }

    /**
     * 提炼处理器：从注解生成 ONodeAttrHolder
     */
    private static Object doDigestHandle(ClassEggg cw, AnnotatedEggg s, Object ref) {
        ONodeAttr attr = s.getElement().getAnnotation(ONodeAttr.class);

        if (attr == null && ref != null) {
            return ref;
        }

        if (s instanceof FieldEggg) {
            return new ONodeAttrHolder(attr, ((Field) s.getElement()).getName());
        } else if (s instanceof PropertyMethodEggg) {
            return new ONodeAttrHolder(attr,
                Property.resolvePropertyName(((Method) s.getElement()).getName()));
        } else if (s instanceof ParamEggg) {
            return new ONodeAttrHolder(attr, ((Parameter) s.getElement()).getName());
        } else {
            return null;
        }
    }

    public static TypeEggg getTypeEggg(Type type) {
        return eggg.getTypeEggg(type);
    }
}
```

在业务代码中读取提炼结果：

```java
TypeEggg typeEggg = EgggUtil.getTypeEggg(clazz);

for (FieldEggg fw : typeEggg.getClassEggg().getAllFieldEgggs()) {
    if (fw.isStatic()) {
        continue;
    }

    // 获取提炼物
    ONodeAttrHolder holder = fw.getDigest();

    // 获取泛型信息
    TypeEggg fieldType = fw.getTypeEggg();

    // 获取别名
    String alias = fw.getAlias();
}
```

### 5、实战：Solon 框架集成示例

以下代码展示了 Solon 框架如何通过 DigestHandler 将字段和参数统一封装为 `FieldSpec` / `ParamSpec`：

```java
public class EgggUtil {
    private static final Eggg eggg = new Eggg()
            .withAliasHandler(EgggUtil::doAliasHandle)
            .withDigestHandler(EgggUtil::doDigestHandle)
            .withReflectHandler(new EgggReflectHandler());

    private static String doAliasHandle(ClassEggg cw, AnnotatedEggg s, String ref) {
        if (s.getDigest() instanceof VarSpec) {
            return s.<VarSpec>getDigest().getName();
        }
        return ref;
    }

    private static Object doDigestHandle(ClassEggg cw, AnnotatedEggg s, Object ref) {
        if (s instanceof FieldEggg) {
            return new FieldSpec((FieldEggg) s);
        } else if (s instanceof ParamEggg) {
            return new ParamSpec((ParamEggg) s);
        }
        return ref;
    }

    public static TypeEggg getTypeEggg(Type type) {
        return eggg.getTypeEggg(type);
    }

    public static ClassEggg getClassEggg(Type type) {
        return getTypeEggg(type).getClassEggg();
    }
}
```

### 6、Creator 机制

除了 Digest 和 Alias，EggG 还支持 **Creator**（创造器）机制，用于指定哪个构造器或静态工厂方法负责创建对象。

#### 注解方式

通过 `withCreatorClass` 注册一个注解类，被该注解标注的构造器或静态方法将被视为创造器：

```java
Eggg eggg = new Eggg()
    .withCreatorClass(ONodeCreator.class);
```

#### 自定义匹配方式

通过 `withCreatorMatcher` 注册自定义的匹配规则：

```java
Eggg eggg = new Eggg()
    .withCreatorMatcher((eggg, executable) -> {
        return executable.isAnnotationPresent(MyCreator.class);
    });
```

#### 获取创造器

```java
ClassEggg cw = eggg.getTypeEggg(MyClass.class).getClassEggg();

ConstrEggg creator = cw.getCreator();

MyClass obj = creator.newInstance();
```

### 7、Handler 执行时机

从调用 `getTypeEggg` 开始，Handler 在元数据创建时自动执行：

```
Eggg.getTypeEggg(type)
  └→ 创建 TypeEggg
     └→ 获取 ClassEggg 时触发
        ├→ 创建 FieldEggg → 自动触发 DigestHandler → 自动触发 AliasHandler
        ├→ 创建 MethodEggg → 自动触发 DigestHandler
        ├→ 创建 ConstrEggg → 自动触发 DigestHandler
        └→ 创建 ParamEggg → 自动触发 DigestHandler → 自动触发 AliasHandler
```

Handler 结果缓存在对应的元数据对象中，后续通过 `getDigest()` 和 `getAlias()` 直接获取。

### 8、设计特点

| 特点 | 说明 |
|---|---|
| 统一入口 | 所有注解解析逻辑集中在 Handler 中 |
| 一次注册 | 不需要在每个使用点重复写解析代码 |
| 可组合 | Digest + Alias + Creator 三个维度独立配置 |
| 可扩展 | 通过 `ReflectHandler` 可自定义反射策略 |
| 缓存友好 | Handler 结果随元数据一起缓存，不重复计算 |

