
EggG 从设计上是框架无关的——它是一套通用的类型分析与元数据提取引擎，任何 Java 项目都可以使用。

本文先给出一套通用集成模板，再分别展示 Snack4（JSON 库）和 Solon（应用框架）的生产集成代码。

### 1、通用集成模板

集成分为三步：**创建单例 → 注册 Handler → 使用**。

**第一步：创建全局 Eggg 单例，注册 Handler**

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

    private static Object doDigestHandle(ClassEggg cw, AnnotatedEggg source, Object ref) {
        // 注解解析逻辑
        return ref;
    }

    private static String doAliasHandle(ClassEggg cw, AnnotatedEggg source, String ref) {
        // 别名生成逻辑
        return ref;
    }

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

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

**第二步：在需要的地方调用**

```java
ClassEggg cw = TypeAnalyzer.analyzeClass(MyModel.class);

for (FieldEggg fw : cw.getAllFieldEgggs()) {
    if (fw.isStatic()) continue;

    String name = fw.getName();
    String alias = fw.getAlias();
    Object digest = fw.getDigest();
    TypeEggg fieldType = fw.getTypeEggg();
    // ... 业务逻辑
}
```

### 2、实战：Snack4（JSON 库）

Snack4 是一个高性能的 Java JSON 处理库，使用 EggG 完成：

1. 序列化时分析字段的泛型类型和注解别名
2. 反序列化时匹配构造器、解析参数别名
3. 通过 Creator 机制支持自定义对象构建

#### EgggUtil 实现

```java
package org.noear.snack4.codec.util;

import org.noear.eggg.*;
import org.noear.snack4.annotation.ONodeAttrHolder;
import org.noear.snack4.annotation.ONodeAttr;
import org.noear.snack4.annotation.ONodeCreator;

import java.lang.reflect.*;

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

    private static String doAliasHandle(ClassEggg cw, AnnotatedEggg s, String ref) {
        if (s.getDigest() instanceof ONodeAttrHolder) {
            return ((ONodeAttrHolder) s.getDigest()).getAlias();
        } else {
            return ref;
        }
    }

    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
// 序列化：遍历字段，按别名输出 JSON 键
TypeEggg typeEggg = EgggUtil.getTypeEggg(clazz);
for (FieldEggg fw : typeEggg.getClassEggg().getAllFieldEgggs()) {
    if (fw.isStatic()) continue;

    String jsonKey = fw.getAlias();      // 使用别名作为 JSON key
    TypeEggg ft = fw.getTypeEggg();       // 字段类型（含泛型）
    Object digest = fw.getDigest();       // ONodeAttrHolder
}
```

### 4、实战：Solon（应用框架）

Solon 是一个轻量级 Java 应用开发框架，使用 EggG 完成：

1. 依赖注入中的类型分析与元数据提取
2. 字段注入时解析参数别名和注解
3. 通过 ReflectHandler 支持原生编译场景

#### EgggUtil 实现

```java
package org.noear.solon.core.util;

import org.noear.eggg.*;
import org.noear.solon.core.wrap.FieldSpec;
import org.noear.solon.core.wrap.ParamSpec;
import org.noear.solon.core.wrap.VarSpec;

import java.lang.reflect.*;

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();
    }
}
```

#### 使用场景

```java
// 依赖注入：分析 Bean 类型的字段和参数
ClassEggg cw = EgggUtil.getClassEggg(beanType);

for (FieldEggg fw : cw.getAllFieldEgggs()) {
    FieldSpec spec = fw.getDigest();     // 自定义的 FieldSpec
    TypeEggg fieldType = fw.getTypeEggg();
    String alias = fw.getAlias();        // 注入名称
}
```

### 5、注意事项

#### Eggg 实例使用全局单例

Eggg 实例是线程安全的，内部使用缓存机制。每次调用都 `new` 一个新实例会导致同一类型被反复解析，失去缓存优势。

```java
// 推荐
private static final Eggg eggg = new Eggg();

// 不推荐
public TypeEggg analyze(Type type) {
    return new Eggg().getTypeEggg(type); // 无缓存
}
```

#### Handler 必须在首次查询之前注册

Handler 在元数据创建时执行，元数据会被缓存。如果先调用 `getTypeEggg()` 再注册 Handler，Handler 不会被执行——因为缓存中已经存在未经 Handler 处理的数据。

```java
// 正确
Eggg eggg = new Eggg()
    .withDigestHandler(this::handle)
    .withAliasHandler(this::handle);
TypeEggg t = eggg.getTypeEggg(type);

// 错误
Eggg eggg = new Eggg();
TypeEggg t = eggg.getTypeEggg(type); // Handler 未注册
eggg.withDigestHandler(this::handle); // 已缓存，不会触发
```

#### 缓存清除

在热部署等特殊场景下（如运行时类被替换），可以手动清除缓存：

```java
eggg.clear(); // 清除所有 TypeEggg 和 ClassEggg 缓存
```

如果需要更精细的清理（例如热插拔项目），也可以按类型、类加载器或包名移除：

```java
eggg.remove(MyPluginClass.class);           // 移除指定类型
eggg.removeByClassLoader(pluginClassLoader); // 移除该类加载器下的所有类型
eggg.removeByPackage("com.example.plugin"); // 移除该包下的所有类型
```

#### FieldEggg 与 PropertyEggg 的区别

- **FieldEggg**：直接访问字段（包括 private），适合框架内部使用
- **PropertyEggg**：通过 getter/setter 访问，适合面向用户的属性模型

```java
// 框架内部：直接字段访问
FieldEggg field = cw.getFieldEgggByName("name");

// 用户 API：走 getter/setter
PropertyEggg prop = cw.getPropertyEgggByName("name");
```
