解密 atlas-mapper 框架 (9/10):故障排查与调试技巧

🎯 学习目标

通过本篇教程,你将学会:

  • 掌握 Atlas Mapper 常见问题的诊断方法
  • 学会使用调试工具和技巧
  • 理解编译时和运行时错误的处理
  • 掌握生产环境问题定位和解决方案

📋 概念讲解:故障排查体系

故障分类和诊断流程

graph TB subgraph "故障分类" A1[编译时错误] --> A2[注解处理器错误] A1 --> A3[代码生成错误] A1 --> A4[依赖冲突错误] B1[运行时错误] --> B2[映射执行错误] B1 --> B3[类型转换错误] B1 --> B4[空值处理错误] C1[性能问题] --> C2[映射速度慢] C1 --> C3[内存泄漏] C1 --> C4[CPU占用高] end subgraph "诊断流程" D1[问题发现] --> D2[信息收集] D2 --> D3[问题分析] D3 --> D4[解决方案] D4 --> D5[验证修复] D5 --> D6[预防措施] end A1 --> D1 B1 --> D1 C1 --> D1 style A1 fill:#ffebee style B1 fill:#fff3e0 style C1 fill:#e8f5e8 style D1 fill:#e3f2fd

调试工具生态

flowchart LR subgraph "开发阶段" A1[IDE调试器] --> A2[断点调试] A3[编译日志] --> A4[注解处理器输出] A5[单元测试] --> A6[集成测试] end subgraph "运行阶段" B1[应用日志] --> B2[映射执行日志] B3[性能监控] --> B4[JVM监控] B5[链路追踪] --> B6[分布式追踪] end subgraph "生产阶段" C1[APM工具] --> C2[性能分析] C3[错误监控] --> C4[告警系统] C5[日志聚合] --> C6[问题定位] end A1 --> B1 B1 --> C1 style A1 fill:#e8f5e8 style B1 fill:#e3f2fd style C1 fill:#fff3e0

🔧 实现步骤:调试工具和技巧

步骤 1:编译时调试工具

注解处理器调试配置

java 复制代码
/**
 * 调试增强的注解处理器
 */
@SupportedAnnotationTypes("io.github.nemoob.atlas.mapper.*")
@SupportedSourceVersion(SourceVersion.RELEASE_8)
public class DebuggableAtlasMapperProcessor extends AbstractProcessor {
    
    private static final String DEBUG_OPTION = "atlas.mapper.debug";
    private static final String VERBOSE_OPTION = "atlas.mapper.verbose";
    
    private boolean debugMode;
    private boolean verboseMode;
    private ProcessingEnvironment processingEnv;
    
    @Override
    public synchronized void init(ProcessingEnvironment processingEnv) {
        super.init(processingEnv);
        this.processingEnv = processingEnv;
        
        // 🔥 读取调试选项
        this.debugMode = Boolean.parseBoolean(
            processingEnv.getOptions().getOrDefault(DEBUG_OPTION, "false"));
        this.verboseMode = Boolean.parseBoolean(
            processingEnv.getOptions().getOrDefault(VERBOSE_OPTION, "false"));
        
        if (debugMode) {
            printDebugInfo("Atlas Mapper 调试模式已启用");
        }
    }
    
    @Override
    public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
        if (roundEnv.processingOver()) {
            return false;
        }
        
        try {
            // 🔥 调试信息收集
            DebugContext debugContext = new DebugContext();
            debugContext.setProcessingRound(getCurrentRound());
            debugContext.setAnnotations(annotations);
            debugContext.setRoundEnvironment(roundEnv);
            
            // 处理 @Mapper 注解
            Set<? extends Element> mapperElements = roundEnv.getElementsAnnotatedWith(Mapper.class);
            
            for (Element element : mapperElements) {
                if (element.getKind() != ElementKind.INTERFACE) {
                    continue;
                }
                
                TypeElement mapperInterface = (TypeElement) element;
                
                try {
                    // 🔥 详细的处理日志
                    debugLog("开始处理 Mapper: " + mapperInterface.getQualifiedName());
                    
                    // 分析 Mapper 接口
                    MapperAnalysisResult analysis = analyzeMapperInterface(mapperInterface, debugContext);
                    
                    // 生成实现类
                    String generatedCode = generateMapperImplementation(analysis, debugContext);
                    
                    // 写入生成的代码
                    writeGeneratedClass(analysis.getImplementationClassName(), generatedCode);
                    
                    debugLog("完成处理 Mapper: " + mapperInterface.getQualifiedName());
                    
                } catch (Exception e) {
                    // 🔥 详细的错误信息
                    handleProcessingError(mapperInterface, e, debugContext);
                }
            }
            
            // 🔥 输出调试报告
            if (debugMode) {
                generateDebugReport(debugContext);
            }
            
            return true;
            
        } catch (Exception e) {
            processingEnv.getMessager().printMessage(
                Diagnostic.Kind.ERROR,
                "Atlas Mapper 处理器发生未预期错误: " + e.getMessage()
            );
            
            if (debugMode) {
                e.printStackTrace();
            }
            
            return false;
        }
    }
    
    /**
     * 🔥 详细的 Mapper 分析
     */
    private MapperAnalysisResult analyzeMapperInterface(TypeElement mapperInterface, DebugContext debugContext) {
        MapperAnalysisResult result = new MapperAnalysisResult();
        result.setMapperInterface(mapperInterface);
        
        // 分析 Mapper 配置
        Mapper mapperAnnotation = mapperInterface.getAnnotation(Mapper.class);
        result.setMapperConfig(mapperAnnotation);
        
        debugLog("Mapper 配置: " + mapperAnnotation);
        
        // 分析映射方法
        List<ExecutableElement> methods = ElementFilter.methodsIn(mapperInterface.getEnclosedElements());
        List<MappingMethodAnalysis> methodAnalyses = new ArrayList<>();
        
        for (ExecutableElement method : methods) {
            if (method.getModifiers().contains(Modifier.DEFAULT) || 
                method.getModifiers().contains(Modifier.STATIC)) {
                continue;
            }
            
            try {
                MappingMethodAnalysis methodAnalysis = analyzeMappingMethod(method, debugContext);
                methodAnalyses.add(methodAnalysis);
                
                debugLog("分析映射方法: " + method.getSimpleName() + 
                        " (" + methodAnalysis.getSourceType() + " -> " + methodAnalysis.getTargetType() + ")");
                
            } catch (Exception e) {
                String errorMsg = String.format("分析映射方法失败 %s.%s: %s", 
                    mapperInterface.getQualifiedName(), method.getSimpleName(), e.getMessage());
                
                processingEnv.getMessager().printMessage(
                    Diagnostic.Kind.ERROR, errorMsg, method);
                
                debugContext.addError(errorMsg, method, e);
            }
        }
        
        result.setMappingMethods(methodAnalyses);
        
        // 验证 Mapper 完整性
        validateMapperCompleteness(result, debugContext);
        
        return result;
    }
    
    /**
     * 🔥 映射方法详细分析
     */
    private MappingMethodAnalysis analyzeMappingMethod(ExecutableElement method, DebugContext debugContext) {
        MappingMethodAnalysis analysis = new MappingMethodAnalysis();
        analysis.setMethod(method);
        
        // 分析参数类型
        List<? extends VariableElement> parameters = method.getParameters();
        if (parameters.size() != 1) {
            throw new ProcessingException("映射方法必须有且仅有一个参数: " + method.getSimpleName());
        }
        
        TypeMirror sourceType = parameters.get(0).asType();
        TypeMirror targetType = method.getReturnType();
        
        analysis.setSourceType(sourceType);
        analysis.setTargetType(targetType);
        
        // 分析 @Mapping 注解
        List<Mapping> mappingAnnotations = Arrays.asList(method.getAnnotationsByType(Mapping.class));
        analysis.setMappingAnnotations(mappingAnnotations);
        
        debugLog("映射注解数量: " + mappingAnnotations.size());
        
        // 分析字段映射关系
        FieldMappingAnalysis fieldAnalysis = analyzeFieldMappings(sourceType, targetType, mappingAnnotations, debugContext);
        analysis.setFieldMappings(fieldAnalysis);
        
        // 检查类型兼容性
        TypeCompatibilityCheck compatibilityCheck = checkTypeCompatibility(sourceType, targetType, debugContext);
        analysis.setCompatibilityCheck(compatibilityCheck);
        
        return analysis;
    }
    
    /**
     * 🔥 字段映射分析
     */
    private FieldMappingAnalysis analyzeFieldMappings(TypeMirror sourceType, TypeMirror targetType, 
                                                     List<Mapping> mappingAnnotations, DebugContext debugContext) {
        
        FieldMappingAnalysis analysis = new FieldMappingAnalysis();
        
        // 获取源类型和目标类型的字段
        Map<String, TypeMirror> sourceFields = getTypeFields(sourceType);
        Map<String, TypeMirror> targetFields = getTypeFields(targetType);
        
        debugLog("源类型字段: " + sourceFields.keySet());
        debugLog("目标类型字段: " + targetFields.keySet());
        
        // 分析显式映射
        Map<String, String> explicitMappings = new HashMap<>();
        for (Mapping mapping : mappingAnnotations) {
            explicitMappings.put(mapping.target(), mapping.source());
        }
        
        // 分析自动映射
        Map<String, String> autoMappings = new HashMap<>();
        for (String targetField : targetFields.keySet()) {
            if (!explicitMappings.containsKey(targetField) && sourceFields.containsKey(targetField)) {
                autoMappings.put(targetField, targetField);
            }
        }
        
        // 检查未映射字段
        Set<String> unmappedTargetFields = new HashSet<>(targetFields.keySet());
        unmappedTargetFields.removeAll(explicitMappings.keySet());
        unmappedTargetFields.removeAll(autoMappings.keySet());
        
        // 检查类型兼容性
        Map<String, TypeCompatibilityIssue> compatibilityIssues = new HashMap<>();
        
        // 检查显式映射的类型兼容性
        for (Map.Entry<String, String> entry : explicitMappings.entrySet()) {
            String targetField = entry.getKey();
            String sourceField = entry.getValue();
            
            TypeMirror sourceFieldType = sourceFields.get(sourceField);
            TypeMirror targetFieldType = targetFields.get(targetField);
            
            if (sourceFieldType != null && targetFieldType != null) {
                if (!isTypeCompatible(sourceFieldType, targetFieldType)) {
                    compatibilityIssues.put(targetField, 
                        new TypeCompatibilityIssue(sourceFieldType, targetFieldType, "类型不兼容"));
                }
            }
        }
        
        // 检查自动映射的类型兼容性
        for (Map.Entry<String, String> entry : autoMappings.entrySet()) {
            String targetField = entry.getKey();
            String sourceField = entry.getValue();
            
            TypeMirror sourceFieldType = sourceFields.get(sourceField);
            TypeMirror targetFieldType = targetFields.get(targetField);
            
            if (!isTypeCompatible(sourceFieldType, targetFieldType)) {
                compatibilityIssues.put(targetField, 
                    new TypeCompatibilityIssue(sourceFieldType, targetFieldType, "自动映射类型不兼容"));
            }
        }
        
        analysis.setExplicitMappings(explicitMappings);
        analysis.setAutoMappings(autoMappings);
        analysis.setUnmappedTargetFields(unmappedTargetFields);
        analysis.setCompatibilityIssues(compatibilityIssues);
        
        // 输出分析结果
        debugLog("显式映射: " + explicitMappings);
        debugLog("自动映射: " + autoMappings);
        debugLog("未映射字段: " + unmappedTargetFields);
        debugLog("兼容性问题: " + compatibilityIssues.size() + " 个");
        
        return analysis;
    }
    
    /**
     * 🔥 错误处理和诊断
     */
    private void handleProcessingError(TypeElement mapperInterface, Exception error, DebugContext debugContext) {
        String errorMessage = String.format("处理 Mapper %s 时发生错误: %s", 
            mapperInterface.getQualifiedName(), error.getMessage());
        
        // 记录错误
        debugContext.addError(errorMessage, mapperInterface, error);
        
        // 生成详细的错误报告
        if (debugMode) {
            generateErrorReport(mapperInterface, error, debugContext);
        }
        
        // 输出编译错误
        processingEnv.getMessager().printMessage(
            Diagnostic.Kind.ERROR, errorMessage, mapperInterface);
        
        // 如果是已知错误类型,提供解决建议
        String suggestion = generateErrorSuggestion(error);
        if (suggestion != null) {
            processingEnv.getMessager().printMessage(
                Diagnostic.Kind.NOTE, "建议: " + suggestion, mapperInterface);
        }
    }
    
    /**
     * 🔥 生成错误解决建议
     */
    private String generateErrorSuggestion(Exception error) {
        String errorMsg = error.getMessage().toLowerCase();
        
        if (errorMsg.contains("cannot find symbol")) {
            return "检查导入语句和类路径配置";
        } else if (errorMsg.contains("incompatible types")) {
            return "检查字段类型兼容性,可能需要自定义类型转换器";
        } else if (errorMsg.contains("unmapped target property")) {
            return "使用 @Mapping 注解指定字段映射关系,或设置 unmappedTargetPolicy = ReportingPolicy.IGNORE";
        } else if (errorMsg.contains("no property named")) {
            return "检查源对象是否包含指定的属性名";
        } else if (errorMsg.contains("ambiguous mapping methods")) {
            return "存在多个匹配的映射方法,请使用 @Named 注解或更具体的方法签名";
        }
        
        return null;
    }
    
    /**
     * 🔥 生成调试报告
     */
    private void generateDebugReport(DebugContext debugContext) {
        StringBuilder report = new StringBuilder();
        report.append("\n=== Atlas Mapper 调试报告 ===\n");
        report.append("处理轮次: ").append(debugContext.getProcessingRound()).append("\n");
        report.append("处理的注解: ").append(debugContext.getAnnotations().size()).append(" 个\n");
        report.append("发现的错误: ").append(debugContext.getErrors().size()).append(" 个\n");
        report.append("发现的警告: ").append(debugContext.getWarnings().size()).append(" 个\n");
        
        // 输出错误详情
        if (!debugContext.getErrors().isEmpty()) {
            report.append("\n--- 错误详情 ---\n");
            for (DebugContext.ErrorInfo error : debugContext.getErrors()) {
                report.append("错误: ").append(error.getMessage()).append("\n");
                report.append("位置: ").append(error.getElement()).append("\n");
                if (error.getException() != null) {
                    report.append("异常: ").append(error.getException().getClass().getSimpleName()).append("\n");
                }
                report.append("\n");
            }
        }
        
        // 输出警告详情
        if (!debugContext.getWarnings().isEmpty()) {
            report.append("\n--- 警告详情 ---\n");
            for (DebugContext.WarningInfo warning : debugContext.getWarnings()) {
                report.append("警告: ").append(warning.getMessage()).append("\n");
                report.append("位置: ").append(warning.getElement()).append("\n");
                report.append("\n");
            }
        }
        
        report.append("=== 调试报告结束 ===\n");
        
        // 输出到编译日志
        processingEnv.getMessager().printMessage(Diagnostic.Kind.NOTE, report.toString());
        
        // 写入调试文件
        try {
            writeDebugFile("atlas-mapper-debug.log", report.toString());
        } catch (IOException e) {
            debugLog("写入调试文件失败: " + e.getMessage());
        }
    }
    
    // 辅助方法
    private void debugLog(String message) {
        if (debugMode) {
            processingEnv.getMessager().printMessage(Diagnostic.Kind.NOTE, "[DEBUG] " + message);
        }
    }
    
    private void printDebugInfo(String message) {
        processingEnv.getMessager().printMessage(Diagnostic.Kind.NOTE, "[INFO] " + message);
    }
    
    private int getCurrentRound() {
        // 实现获取当前处理轮次的逻辑
        return 1;
    }
    
    // 其他辅助方法...
}

Maven 调试配置

xml 复制代码
<!-- pom.xml 中的调试配置 -->
<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-compiler-plugin</artifactId>
    <version>3.8.1</version>
    <configuration>
        <source>8</source>
        <target>8</target>
        <annotationProcessorPaths>
            <path>
                <groupId>io.github.nemoob</groupId>
                <artifactId>atlas-mapper-processor</artifactId>
                <version>1.0.0</version>
            </path>
        </annotationProcessorPaths>
        <compilerArgs>
            <!-- 🔥 启用调试模式 -->
            <arg>-Aatlas.mapper.debug=true</arg>
            <arg>-Aatlas.mapper.verbose=true</arg>
            
            <!-- 🔥 输出详细编译信息 -->
            <arg>-verbose</arg>
            <arg>-Xlint:all</arg>
            
            <!-- 🔥 保留生成的源文件 -->
            <arg>-s</arg>
            <arg>${project.build.directory}/generated-sources/annotations</arg>
        </compilerArgs>
        <showWarnings>true</showWarnings>
        <showDeprecation>true</showDeprecation>
    </configuration>
</plugin>

<!-- 🔥 生成源码插件 -->
<plugin>
    <groupId>org.codehaus.mojo</groupId>
    <artifactId>build-helper-maven-plugin</artifactId>
    <version>3.2.0</version>
    <executions>
        <execution>
            <id>add-source</id>
            <phase>generate-sources</phase>
            <goals>
                <goal>add-source</goal>
            </goals>
            <configuration>
                <sources>
                    <source>${project.build.directory}/generated-sources/annotations</source>
                </sources>
            </configuration>
        </execution>
    </executions>
</plugin>

步骤 2:运行时调试工具

映射执行监控器

java 复制代码
/**
 * 运行时映射监控和调试工具
 */
@Component
public class MappingRuntimeDebugger {
    
    private static final Logger log = LoggerFactory.getLogger(MappingRuntimeDebugger.class);
    
    // 🔥 映射执行追踪
    private final ThreadLocal<MappingExecutionContext> executionContext = new ThreadLocal<>();
    
    // 🔥 错误收集器
    private final List<MappingError> recentErrors = Collections.synchronizedList(new ArrayList<>());
    
    // 🔥 性能统计
    private final Map<String, MappingStats> mappingStats = new ConcurrentHashMap<>();
    
    /**
     * 🔥 开始映射追踪
     */
    public void startMappingTrace(String mapperName, String methodName, Object source) {
        MappingExecutionContext context = new MappingExecutionContext();
        context.setMapperName(mapperName);
        context.setMethodName(methodName);
        context.setSourceObject(source);
        context.setStartTime(System.nanoTime());
        context.setThreadName(Thread.currentThread().getName());
        context.setTraceId(generateTraceId());
        
        executionContext.set(context);
        
        log.debug("开始映射追踪 [{}] {}.{} - 源对象类型: {}", 
            context.getTraceId(), mapperName, methodName, 
            source != null ? source.getClass().getSimpleName() : "null");
    }
    
    /**
     * 🔥 结束映射追踪
     */
    public void endMappingTrace(Object result) {
        MappingExecutionContext context = executionContext.get();
        if (context == null) {
            return;
        }
        
        try {
            long executionTime = System.nanoTime() - context.getStartTime();
            context.setExecutionTime(executionTime);
            context.setResultObject(result);
            
            // 更新统计信息
            updateMappingStats(context);
            
            log.debug("完成映射追踪 [{}] {}.{} - 执行时间: {:.2f}ms, 结果类型: {}", 
                context.getTraceId(), context.getMapperName(), context.getMethodName(),
                executionTime / 1_000_000.0, 
                result != null ? result.getClass().getSimpleName() : "null");
                
        } finally {
            executionContext.remove();
        }
    }
    
    /**
     * 🔥 记录映射错误
     */
    public void recordMappingError(Exception error) {
        MappingExecutionContext context = executionContext.get();
        if (context == null) {
            return;
        }
        
        MappingError mappingError = new MappingError();
        mappingError.setTraceId(context.getTraceId());
        mappingError.setMapperName(context.getMapperName());
        mappingError.setMethodName(context.getMethodName());
        mappingError.setSourceObject(context.getSourceObject());
        mappingError.setError(error);
        mappingError.setTimestamp(Instant.now());
        mappingError.setThreadName(context.getThreadName());
        
        // 添加到错误列表
        recentErrors.add(mappingError);
        
        // 保持错误列表大小
        if (recentErrors.size() > 1000) {
            recentErrors.remove(0);
        }
        
        // 记录详细错误日志
        log.error("映射执行错误 [{}] {}.{} - 错误: {}", 
            context.getTraceId(), context.getMapperName(), context.getMethodName(),
            error.getMessage(), error);
        
        // 生成错误诊断报告
        generateErrorDiagnostics(mappingError);
    }
    
    /**
     * 🔥 字段映射调试
     */
    public void debugFieldMapping(String sourceField, Object sourceValue, 
                                 String targetField, Object targetValue) {
        MappingExecutionContext context = executionContext.get();
        if (context == null) {
            return;
        }
        
        FieldMappingDebugInfo debugInfo = new FieldMappingDebugInfo();
        debugInfo.setSourceField(sourceField);
        debugInfo.setSourceValue(sourceValue);
        debugInfo.setTargetField(targetField);
        debugInfo.setTargetValue(targetValue);
        debugInfo.setSourceType(sourceValue != null ? sourceValue.getClass() : null);
        debugInfo.setTargetType(targetValue != null ? targetValue.getClass() : null);
        
        context.addFieldMapping(debugInfo);
        
        log.trace("字段映射 [{}] {} ({}) -> {} ({}): {} -> {}", 
            context.getTraceId(), sourceField, 
            debugInfo.getSourceType() != null ? debugInfo.getSourceType().getSimpleName() : "null",
            targetField,
            debugInfo.getTargetType() != null ? debugInfo.getTargetType().getSimpleName() : "null",
            sourceValue, targetValue);
    }
    
    /**
     * 🔥 类型转换调试
     */
    public void debugTypeConversion(Object sourceValue, Object targetValue, String converterName) {
        MappingExecutionContext context = executionContext.get();
        if (context == null) {
            return;
        }
        
        TypeConversionDebugInfo debugInfo = new TypeConversionDebugInfo();
        debugInfo.setSourceValue(sourceValue);
        debugInfo.setTargetValue(targetValue);
        debugInfo.setSourceType(sourceValue != null ? sourceValue.getClass() : null);
        debugInfo.setTargetType(targetValue != null ? targetValue.getClass() : null);
        debugInfo.setConverterName(converterName);
        
        context.addTypeConversion(debugInfo);
        
        log.trace("类型转换 [{}] {} -> {} 使用转换器: {}", 
            context.getTraceId(), 
            debugInfo.getSourceType() != null ? debugInfo.getSourceType().getSimpleName() : "null",
            debugInfo.getTargetType() != null ? debugInfo.getTargetType().getSimpleName() : "null",
            converterName);
    }
    
    /**
     * 🔥 生成映射执行报告
     */
    public MappingExecutionReport generateExecutionReport(String traceId) {
        // 从执行历史中查找
        MappingExecutionContext context = findExecutionContext(traceId);
        if (context == null) {
            return null;
        }
        
        MappingExecutionReport report = new MappingExecutionReport();
        report.setTraceId(traceId);
        report.setMapperName(context.getMapperName());
        report.setMethodName(context.getMethodName());
        report.setExecutionTime(context.getExecutionTime());
        report.setSourceObject(context.getSourceObject());
        report.setResultObject(context.getResultObject());
        report.setFieldMappings(context.getFieldMappings());
        report.setTypeConversions(context.getTypeConversions());
        
        return report;
    }
    
    /**
     * 🔥 生成错误诊断报告
     */
    private void generateErrorDiagnostics(MappingError mappingError) {
        StringBuilder diagnostics = new StringBuilder();
        diagnostics.append("\n=== 映射错误诊断报告 ===\n");
        diagnostics.append("追踪ID: ").append(mappingError.getTraceId()).append("\n");
        diagnostics.append("映射器: ").append(mappingError.getMapperName()).append("\n");
        diagnostics.append("方法: ").append(mappingError.getMethodName()).append("\n");
        diagnostics.append("线程: ").append(mappingError.getThreadName()).append("\n");
        diagnostics.append("时间: ").append(mappingError.getTimestamp()).append("\n");
        
        // 源对象信息
        if (mappingError.getSourceObject() != null) {
            diagnostics.append("源对象类型: ").append(mappingError.getSourceObject().getClass().getName()).append("\n");
            diagnostics.append("源对象内容: ").append(objectToString(mappingError.getSourceObject())).append("\n");
        }
        
        // 错误信息
        Exception error = mappingError.getError();
        diagnostics.append("错误类型: ").append(error.getClass().getName()).append("\n");
        diagnostics.append("错误消息: ").append(error.getMessage()).append("\n");
        
        // 错误分析和建议
        String analysis = analyzeError(error);
        if (analysis != null) {
            diagnostics.append("错误分析: ").append(analysis).append("\n");
        }
        
        String suggestion = suggestErrorSolution(error);
        if (suggestion != null) {
            diagnostics.append("解决建议: ").append(suggestion).append("\n");
        }
        
        diagnostics.append("=== 诊断报告结束 ===\n");
        
        log.warn(diagnostics.toString());
    }
    
    /**
     * 🔥 错误分析
     */
    private String analyzeError(Exception error) {
        String errorMsg = error.getMessage();
        String errorType = error.getClass().getSimpleName();
        
        if (error instanceof NullPointerException) {
            return "空指针异常,可能是源对象或其某个属性为 null";
        } else if (error instanceof ClassCastException) {
            return "类型转换异常,源类型和目标类型不兼容";
        } else if (error instanceof IllegalArgumentException) {
            return "非法参数异常,传入的参数不符合预期";
        } else if (errorMsg != null && errorMsg.contains("Cannot map")) {
            return "映射失败,可能是缺少对应的映射方法或类型转换器";
        } else if (errorMsg != null && errorMsg.contains("Ambiguous")) {
            return "映射方法模糊,存在多个匹配的映射方法";
        }
        
        return "未知错误类型: " + errorType;
    }
    
    /**
     * 🔥 错误解决建议
     */
    private String suggestErrorSolution(Exception error) {
        String errorMsg = error.getMessage();
        
        if (error instanceof NullPointerException) {
            return "1. 检查源对象是否为 null\n2. 使用 @Mapping(nullValueMappingStrategy = NullValueMappingStrategy.RETURN_DEFAULT) 处理 null 值\n3. 在映射前进行 null 检查";
        } else if (error instanceof ClassCastException) {
            return "1. 检查字段类型是否匹配\n2. 添加自定义类型转换器\n3. 使用 @Mapping(qualifiedByName = \"customConverter\") 指定转换方法";
        } else if (errorMsg != null && errorMsg.contains("Cannot map")) {
            return "1. 检查是否缺少映射方法\n2. 添加 @Mapping 注解指定字段映射\n3. 实现自定义映射逻辑";
        } else if (errorMsg != null && errorMsg.contains("Ambiguous")) {
            return "1. 使用 @Named 注解区分映射方法\n2. 使用更具体的方法签名\n3. 指定 qualifiedByName 属性";
        }
        
        return "请查看完整的堆栈跟踪信息,并参考 Atlas Mapper 文档";
    }
    
    // 辅助方法
    private void updateMappingStats(MappingExecutionContext context) {
        String key = context.getMapperName() + "." + context.getMethodName();
        mappingStats.compute(key, (k, stats) -> {
            if (stats == null) {
                stats = new MappingStats();
                stats.setMapperName(context.getMapperName());
                stats.setMethodName(context.getMethodName());
            }
            
            stats.incrementExecutionCount();
            stats.addExecutionTime(context.getExecutionTime());
            stats.updateLastExecutionTime(Instant.now());
            
            return stats;
        });
    }
    
    private String generateTraceId() {
        return UUID.randomUUID().toString().substring(0, 8);
    }
    
    private MappingExecutionContext findExecutionContext(String traceId) {
        // 实现从执行历史中查找上下文的逻辑
        return null;
    }
    
    private String objectToString(Object obj) {
        try {
            return obj.toString();
        } catch (Exception e) {
            return obj.getClass().getName() + "@" + Integer.toHexString(obj.hashCode());
        }
    }
    
    /**
     * 映射执行上下文
     */
    @Data
    public static class MappingExecutionContext {
        private String traceId;
        private String mapperName;
        private String methodName;
        private Object sourceObject;
        private Object resultObject;
        private long startTime;
        private long executionTime;
        private String threadName;
        private List<FieldMappingDebugInfo> fieldMappings = new ArrayList<>();
        private List<TypeConversionDebugInfo> typeConversions = new ArrayList<>();
        
        public void addFieldMapping(FieldMappingDebugInfo debugInfo) {
            fieldMappings.add(debugInfo);
        }
        
        public void addTypeConversion(TypeConversionDebugInfo debugInfo) {
            typeConversions.add(debugInfo);
        }
    }
    
    /**
     * 字段映射调试信息
     */
    @Data
    public static class FieldMappingDebugInfo {
        private String sourceField;
        private Object sourceValue;
        private Class<?> sourceType;
        private String targetField;
        private Object targetValue;
        private Class<?> targetType;
    }
    
    /**
     * 类型转换调试信息
     */
    @Data
    public static class TypeConversionDebugInfo {
        private Object sourceValue;
        private Object targetValue;
        private Class<?> sourceType;
        private Class<?> targetType;
        private String converterName;
    }
    
    /**
     * 映射错误信息
     */
    @Data
    public static class MappingError {
        private String traceId;
        private String mapperName;
        private String methodName;
        private Object sourceObject;
        private Exception error;
        private Instant timestamp;
        private String threadName;
    }
    
    /**
     * 映射统计信息
     */
    @Data
    public static class MappingStats {
        private String mapperName;
        private String methodName;
        private long executionCount;
        private long totalExecutionTime;
        private long minExecutionTime = Long.MAX_VALUE;
        private long maxExecutionTime = Long.MIN_VALUE;
        private Instant lastExecutionTime;
        
        public void incrementExecutionCount() {
            executionCount++;
        }
        
        public void addExecutionTime(long time) {
            totalExecutionTime += time;
            minExecutionTime = Math.min(minExecutionTime, time);
            maxExecutionTime = Math.max(maxExecutionTime, time);
        }
        
        public void updateLastExecutionTime(Instant time) {
            lastExecutionTime = time;
        }
        
        public double getAverageExecutionTime() {
            return executionCount > 0 ? (double) totalExecutionTime / executionCount : 0;
        }
    }
    
    /**
     * 映射执行报告
     */
    @Data
    public static class MappingExecutionReport {
        private String traceId;
        private String mapperName;
        private String methodName;
        private long executionTime;
        private Object sourceObject;
        private Object resultObject;
        private List<FieldMappingDebugInfo> fieldMappings;
        private List<TypeConversionDebugInfo> typeConversions;
    }
}

步骤 3:调试 AOP 切面

java 复制代码
/**
 * 映射调试切面
 */
@Aspect
@Component
@ConditionalOnProperty(name = "atlas.mapper.debug.enabled", havingValue = "true")
public class MappingDebugAspect {
    
    private static final Logger log = LoggerFactory.getLogger(MappingDebugAspect.class);
    
    private final MappingRuntimeDebugger debugger;
    
    public MappingDebugAspect(MappingRuntimeDebugger debugger) {
        this.debugger = debugger;
    }
    
    /**
     * 🔥 拦截所有映射方法调用
     */
    @Around("execution(* *..*.*(..)) && @within(io.github.nemoob.atlas.mapper.Mapper)")
    public Object debugMappingExecution(ProceedingJoinPoint joinPoint) throws Throwable {
        String mapperName = joinPoint.getTarget().getClass().getSimpleName();
        String methodName = joinPoint.getSignature().getName();
        Object[] args = joinPoint.getArgs();
        Object source = args.length > 0 ? args[0] : null;
        
        // 开始追踪
        debugger.startMappingTrace(mapperName, methodName, source);
        
        try {
            // 执行映射
            Object result = joinPoint.proceed();
            
            // 结束追踪
            debugger.endMappingTrace(result);
            
            return result;
            
        } catch (Exception e) {
            // 记录错误
            debugger.recordMappingError(e);
            throw e;
        }
    }
    
    /**
     * 🔥 拦截字段访问(需要编译时织入)
     */
    @Around("get(* *.*) && within(@io.github.nemoob.atlas.mapper.Mapper *)")
    public Object debugFieldAccess(ProceedingJoinPoint joinPoint) throws Throwable {
        String fieldName = joinPoint.getSignature().getName();
        Object result = joinPoint.proceed();
        
        log.trace("字段访问: {} = {}", fieldName, result);
        
        return result;
    }
    
    /**
     * 🔥 拦截方法调用异常
     */
    @AfterThrowing(pointcut = "execution(* *..*.*(..)) && @within(io.github.nemoob.atlas.mapper.Mapper)", 
                   throwing = "exception")
    public void handleMappingException(JoinPoint joinPoint, Exception exception) {
        String mapperName = joinPoint.getTarget().getClass().getSimpleName();
        String methodName = joinPoint.getSignature().getName();
        
        log.error("映射方法异常 {}.{}: {}", mapperName, methodName, exception.getMessage(), exception);
        
        // 生成异常分析报告
        generateExceptionAnalysis(joinPoint, exception);
    }
    
    /**
     * 🔥 生成异常分析报告
     */
    private void generateExceptionAnalysis(JoinPoint joinPoint, Exception exception) {
        StringBuilder analysis = new StringBuilder();
        analysis.append("\n=== 映射异常分析 ===\n");
        analysis.append("映射器: ").append(joinPoint.getTarget().getClass().getName()).append("\n");
        analysis.append("方法: ").append(joinPoint.getSignature().getName()).append("\n");
        analysis.append("参数: ");
        
        Object[] args = joinPoint.getArgs();
        for (int i = 0; i < args.length; i++) {
            if (i > 0) analysis.append(", ");
            analysis.append("arg").append(i).append("=");
            if (args[i] != null) {
                analysis.append(args[i].getClass().getSimpleName()).append("@")
                        .append(Integer.toHexString(args[i].hashCode()));
            } else {
                analysis.append("null");
            }
        }
        analysis.append("\n");
        
        analysis.append("异常类型: ").append(exception.getClass().getName()).append("\n");
        analysis.append("异常消息: ").append(exception.getMessage()).append("\n");
        
        // 堆栈跟踪分析
        StackTraceElement[] stackTrace = exception.getStackTrace();
        if (stackTrace.length > 0) {
            analysis.append("异常位置: ").append(stackTrace[0]).append("\n");
        }
        
        analysis.append("=== 分析结束 ===\n");
        
        log.error(analysis.toString());
    }
}

💻 示例代码:常见问题解决方案

示例 1:编译时问题诊断

java 复制代码
/**
 * 编译时问题诊断工具
 */
public class CompileTimeDiagnostics {
    
    /**
     * 🔥 诊断注解处理器问题
     */
    public static void diagnoseAnnotationProcessor() {
        System.out.println("=== 注解处理器诊断 ===");
        
        // 检查注解处理器是否在类路径中
        try {
            Class.forName("io.github.nemoob.atlas.mapper.processor.AtlasMapperProcessor");
            System.out.println("✓ 注解处理器类已找到");
        } catch (ClassNotFoundException e) {
            System.out.println("✗ 注解处理器类未找到,请检查依赖配置");
            System.out.println("  解决方案:添加 atlas-mapper-processor 依赖");
        }
        
        // 检查 META-INF/services 配置
        try {
            ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
            URL serviceFile = classLoader.getResource("META-INF/services/javax.annotation.processing.Processor");
            if (serviceFile != null) {
                System.out.println("✓ 注解处理器服务配置已找到");
                
                // 读取配置内容
                try (BufferedReader reader = new BufferedReader(
                        new InputStreamReader(serviceFile.openStream()))) {
                    String line;
                    while ((line = reader.readLine()) != null) {
                        System.out.println("  处理器: " + line);
                    }
                }
            } else {
                System.out.println("✗ 注解处理器服务配置未找到");
                System.out.println("  解决方案:检查 META-INF/services/javax.annotation.processing.Processor 文件");
            }
        } catch (IOException e) {
            System.out.println("✗ 读取服务配置失败: " + e.getMessage());
        }
        
        // 检查编译器参数
        String javaVersion = System.getProperty("java.version");
        System.out.println("Java 版本: " + javaVersion);
        
        if (javaVersion.startsWith("1.8") || javaVersion.startsWith("8")) {
            System.out.println("✓ Java 版本兼容");
        } else {
            System.out.println("⚠ Java 版本可能不兼容,推荐使用 Java 8");
        }
    }
    
    /**
     * 🔥 诊断依赖冲突
     */
    public static void diagnoseDependencyConflicts() {
        System.out.println("\n=== 依赖冲突诊断 ===");
        
        // 检查关键依赖
        String[] criticalDependencies = {
            "io.github.nemoob.atlas.mapper.Mapper",
            "io.github.nemoob.atlas.mapper.Mapping",
            "org.springframework.stereotype.Component",
            "org.freemarker.template.Template"
        };
        
        for (String className : criticalDependencies) {
            try {
                Class<?> clazz = Class.forName(className);
                URL location = clazz.getProtectionDomain().getCodeSource().getLocation();
                System.out.println("✓ " + className + " -> " + location);
            } catch (ClassNotFoundException e) {
                System.out.println("✗ " + className + " 未找到");
            }
        }
        
        // 检查版本冲突
        checkVersionConflicts();
    }
    
    /**
     * 🔥 检查版本冲突
     */
    private static void checkVersionConflicts() {
        System.out.println("\n--- 版本冲突检查 ---");
        
        // 检查 Spring 版本
        try {
            Class<?> springVersion = Class.forName("org.springframework.core.SpringVersion");
            Method getVersionMethod = springVersion.getMethod("getVersion");
            String version = (String) getVersionMethod.invoke(null);
            System.out.println("Spring 版本: " + version);
            
            if (version != null && version.startsWith("5.2")) {
                System.out.println("✓ Spring 版本兼容");
            } else {
                System.out.println("⚠ Spring 版本可能不兼容,推荐使用 5.2.x");
            }
        } catch (Exception e) {
            System.out.println("无法检测 Spring 版本");
        }
        
        // 检查 Spring Boot 版本
        try {
            Class<?> springBootVersion = Class.forName("org.springframework.boot.SpringBootVersion");
            Method getVersionMethod = springBootVersion.getMethod("getVersion");
            String version = (String) getVersionMethod.invoke(null);
            System.out.println("Spring Boot 版本: " + version);
            
            if (version != null && version.startsWith("2.2")) {
                System.out.println("✓ Spring Boot 版本兼容");
            } else {
                System.out.println("⚠ Spring Boot 版本可能不兼容,推荐使用 2.2.x");
            }
        } catch (Exception e) {
            System.out.println("无法检测 Spring Boot 版本");
        }
    }
    
    /**
     * 🔥 生成诊断报告
     */
    public static void generateDiagnosticReport() {
        System.out.println("\n=== 完整诊断报告 ===");
        
        diagnoseAnnotationProcessor();
        diagnoseDependencyConflicts();
        
        System.out.println("\n=== 系统信息 ===");
        System.out.println("操作系统: " + System.getProperty("os.name"));
        System.out.println("Java 版本: " + System.getProperty("java.version"));
        System.out.println("Java 厂商: " + System.getProperty("java.vendor"));
        System.out.println("类路径: " + System.getProperty("java.class.path"));
        
        System.out.println("\n=== 诊断完成 ===");
    }
}

示例 2:运行时问题排查

java 复制代码
/**
 * 运行时问题排查工具
 */
@Component
public class RuntimeTroubleshooter {
    
    private static final Logger log = LoggerFactory.getLogger(RuntimeTroubleshooter.class);
    
    private final ApplicationContext applicationContext;
    private final MappingRuntimeDebugger debugger;
    
    public RuntimeTroubleshooter(ApplicationContext applicationContext, 
                               MappingRuntimeDebugger debugger) {
        this.applicationContext = applicationContext;
        this.debugger = debugger;
    }
    
    /**
     * 🔥 检查 Mapper Bean 注册
     */
    public void checkMapperBeans() {
        log.info("=== Mapper Bean 检查 ===");
        
        // 获取所有 Mapper Bean
        Map<String, Object> mapperBeans = applicationContext.getBeansWithAnnotation(Mapper.class);
        
        if (mapperBeans.isEmpty()) {
            log.warn("未找到任何 Mapper Bean");
            log.info("可能的原因:");
            log.info("1. 注解处理器未正确执行");
            log.info("2. 生成的实现类未被 Spring 扫描到");
            log.info("3. @ComponentScan 配置不正确");
            return;
        }
        
        log.info("找到 {} 个 Mapper Bean:", mapperBeans.size());
        
        for (Map.Entry<String, Object> entry : mapperBeans.entrySet()) {
            String beanName = entry.getKey();
            Object bean = entry.getValue();
            Class<?> beanClass = bean.getClass();
            
            log.info("- {}: {} ({})", beanName, beanClass.getName(), 
                    beanClass.isInterface() ? "接口" : "实现类");
            
            // 检查是否是代理对象
            if (AopUtils.isAopProxy(bean)) {
                log.info("  └─ 这是一个 AOP 代理对象");
                Class<?> targetClass = AopUtils.getTargetClass(bean);
                log.info("  └─ 目标类: {}", targetClass.getName());
            }
            
            // 检查方法
            Method[] methods = beanClass.getDeclaredMethods();
            log.info("  └─ 方法数量: {}", methods.length);
            
            for (Method method : methods) {
                if (!method.isSynthetic() && !method.isBridge()) {
                    log.debug("    └─ {}", method.getName());
                }
            }
        }
    }
    
    /**
     * 🔥 测试映射功能
     */
    public void testMappingFunctionality() {
        log.info("=== 映射功能测试 ===");
        
        try {
            // 获取 UserMapper Bean
            UserMapper userMapper = applicationContext.getBean(UserMapper.class);
            log.info("✓ UserMapper Bean 获取成功");
            
            // 创建测试数据
            User testUser = createTestUser();
            log.info("✓ 测试用户创建成功: {}", testUser);
            
            // 执行映射
            UserDto userDto = userMapper.toDto(testUser);
            log.info("✓ 映射执行成功: {}", userDto);
            
            // 验证映射结果
            validateMappingResult(testUser, userDto);
            
        } catch (NoSuchBeanDefinitionException e) {
            log.error("✗ UserMapper Bean 未找到: {}", e.getMessage());
            log.info("解决方案:");
            log.info("1. 检查 @Mapper 注解是否正确");
            log.info("2. 检查注解处理器是否正确执行");
            log.info("3. 检查生成的实现类是否存在");
            
        } catch (Exception e) {
            log.error("✗ 映射执行失败: {}", e.getMessage(), e);
            
            // 分析错误原因
            analyzeRuntimeError(e);
        }
    }
    
    /**
     * 🔥 分析运行时错误
     */
    private void analyzeRuntimeError(Exception error) {
        log.info("=== 运行时错误分析 ===");
        
        String errorType = error.getClass().getSimpleName();
        String errorMessage = error.getMessage();
        
        log.info("错误类型: {}", errorType);
        log.info("错误消息: {}", errorMessage);
        
        // 根据错误类型提供解决方案
        switch (errorType) {
            case "NullPointerException":
                log.info("可能原因:");
                log.info("1. 源对象为 null");
                log.info("2. 源对象的某个属性为 null");
                log.info("3. 映射过程中访问了 null 对象的方法");
                log.info("解决方案:");
                log.info("1. 在映射前检查源对象是否为 null");
                log.info("2. 使用 @Mapping(nullValueMappingStrategy = NullValueMappingStrategy.RETURN_DEFAULT)");
                log.info("3. 在源对象的 getter 方法中添加 null 检查");
                break;
                
            case "ClassCastException":
                log.info("可能原因:");
                log.info("1. 字段类型不匹配");
                log.info("2. 缺少类型转换器");
                log.info("3. 泛型类型擦除导致的问题");
                log.info("解决方案:");
                log.info("1. 检查源字段和目标字段的类型");
                log.info("2. 添加自定义类型转换器");
                log.info("3. 使用 @Mapping(qualifiedByName = \"customConverter\")");
                break;
                
            case "IllegalArgumentException":
                log.info("可能原因:");
                log.info("1. 传入的参数不符合预期");
                log.info("2. 枚举值转换失败");
                log.info("3. 日期格式转换失败");
                log.info("解决方案:");
                log.info("1. 检查传入参数的有效性");
                log.info("2. 添加参数验证");
                log.info("3. 使用自定义转换器处理特殊情况");
                break;
                
            default:
                log.info("未知错误类型,请查看完整的堆栈跟踪信息");
                break;
        }
        
        // 输出堆栈跟踪的关键部分
        StackTraceElement[] stackTrace = error.getStackTrace();
        log.info("关键堆栈信息:");
        for (int i = 0; i < Math.min(5, stackTrace.length); i++) {
            StackTraceElement element = stackTrace[i];
            if (element.getClassName().contains("atlas.mapper") || 
                element.getClassName().contains("Mapper")) {
                log.info("  at {}.{}({}:{})", 
                    element.getClassName(), element.getMethodName(),
                    element.getFileName(), element.getLineNumber());
            }
        }
    }
    
    /**
     * 🔥 验证映射结果
     */
    private void validateMappingResult(User source, UserDto target) {
        log.info("=== 映射结果验证 ===");
        
        boolean valid = true;
        
        // 验证基本字段
        if (!Objects.equals(source.getId(), target.getId())) {
            log.warn("✗ ID 字段映射不正确: {} -> {}", source.getId(), target.getId());
            valid = false;
        } else {
            log.info("✓ ID 字段映射正确");
        }
        
        if (!Objects.equals(source.getName(), target.getName())) {
            log.warn("✗ Name 字段映射不正确: {} -> {}", source.getName(), target.getName());
            valid = false;
        } else {
            log.info("✓ Name 字段映射正确");
        }
        
        if (!Objects.equals(source.getEmail(), target.getEmail())) {
            log.warn("✗ Email 字段映射不正确: {} -> {}", source.getEmail(), target.getEmail());
            valid = false;
        } else {
            log.info("✓ Email 字段映射正确");
        }
        
        // 验证日期字段
        if (source.getCreatedAt() != null && target.getCreatedAt() != null) {
            String expectedDateStr = source.getCreatedAt().format(DateTimeFormatter.ISO_LOCAL_DATE_TIME);
            if (!expectedDateStr.equals(target.getCreatedAt())) {
                log.warn("✗ CreatedAt 字段映射不正确: {} -> {}", expectedDateStr, target.getCreatedAt());
                valid = false;
            } else {
                log.info("✓ CreatedAt 字段映射正确");
            }
        }
        
        if (valid) {
            log.info("✓ 所有字段映射验证通过");
        } else {
            log.warn("✗ 存在字段映射问题,请检查映射配置");
        }
    }
    
    /**
     * 🔥 性能问题诊断
     */
    public void diagnosePerformanceIssues() {
        log.info("=== 性能问题诊断 ===");
        
        // 检查 JVM 内存使用
        Runtime runtime = Runtime.getRuntime();
        long maxMemory = runtime.maxMemory();
        long totalMemory = runtime.totalMemory();
        long freeMemory = runtime.freeMemory();
        long usedMemory = totalMemory - freeMemory;
        
        log.info("JVM 内存使用情况:");
        log.info("- 最大内存: {} MB", maxMemory / 1024 / 1024);
        log.info("- 总内存: {} MB", totalMemory / 1024 / 1024);
        log.info("- 已使用: {} MB ({:.1f}%)", usedMemory / 1024 / 1024, 
                (double) usedMemory / totalMemory * 100);
        log.info("- 空闲内存: {} MB", freeMemory / 1024 / 1024);
        
        if ((double) usedMemory / totalMemory > 0.8) {
            log.warn("⚠ 内存使用率过高,可能影响映射性能");
            log.info("建议:");
            log.info("1. 增加 JVM 堆内存大小 (-Xmx)");
            log.info("2. 优化映射逻辑,减少对象创建");
            log.info("3. 使用对象池或缓存策略");
        }
        
        // 检查 GC 情况
        List<GarbageCollectorMXBean> gcBeans = ManagementFactory.getGarbageCollectorMXBeans();
        log.info("垃圾收集器信息:");
        for (GarbageCollectorMXBean gcBean : gcBeans) {
            log.info("- {}: 收集次数={}, 收集时间={}ms", 
                    gcBean.getName(), gcBean.getCollectionCount(), gcBean.getCollectionTime());
        }
        
        // 检查线程情况
        ThreadMXBean threadBean = ManagementFactory.getThreadMXBean();
        log.info("线程信息:");
        log.info("- 活跃线程数: {}", threadBean.getThreadCount());
        log.info("- 守护线程数: {}", threadBean.getDaemonThreadCount());
        log.info("- 峰值线程数: {}", threadBean.getPeakThreadCount());
    }
    
    /**
     * 🔥 生成完整的故障排查报告
     */
    public void generateTroubleshootingReport() {
        log.info("=== Atlas Mapper 故障排查报告 ===");
        
        checkMapperBeans();
        testMappingFunctionality();
        diagnosePerformanceIssues();
        
        log.info("=== 故障排查完成 ===");
    }
    
    // 辅助方法
    private User createTestUser() {
        User user = new User();
        user.setId(1L);
        user.setName("测试用户");
        user.setEmail("test@example.com");
        user.setCreatedAt(LocalDateTime.now());
        user.setUpdatedAt(LocalDateTime.now());
        return user;
    }
}

示例 3:调试 REST API

java 复制代码
/**
 * 调试和故障排查 REST API
 */
@RestController
@RequestMapping("/api/debug")
@ConditionalOnProperty(name = "atlas.mapper.debug.api.enabled", havingValue = "true")
public class MappingDebugController {
    
    private final RuntimeTroubleshooter troubleshooter;
    private final MappingRuntimeDebugger debugger;
    private final CompileTimeDiagnostics diagnostics;
    
    public MappingDebugController(RuntimeTroubleshooter troubleshooter,
                                MappingRuntimeDebugger debugger) {
        this.troubleshooter = troubleshooter;
        this.debugger = debugger;
        this.diagnostics = new CompileTimeDiagnostics();
    }
    
    /**
     * 🔥 执行完整的故障排查
     */
    @GetMapping("/troubleshoot")
    public ResponseEntity<Map<String, Object>> troubleshoot() {
        Map<String, Object> result = new HashMap<>();
        
        try {
            // 执行故障排查
            troubleshooter.generateTroubleshootingReport();
            
            result.put("status", "success");
            result.put("message", "故障排查完成,请查看日志获取详细信息");
            result.put("timestamp", Instant.now());
            
            return ResponseEntity.ok(result);
            
        } catch (Exception e) {
            result.put("status", "error");
            result.put("message", "故障排查失败: " + e.getMessage());
            result.put("timestamp", Instant.now());
            
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(result);
        }
    }
    
    /**
     * 🔥 检查 Mapper Bean 状态
     */
    @GetMapping("/mappers")
    public ResponseEntity<Map<String, Object>> checkMappers() {
        Map<String, Object> result = new HashMap<>();
        
        try {
            troubleshooter.checkMapperBeans();
            
            result.put("status", "success");
            result.put("message", "Mapper Bean 检查完成");
            result.put("timestamp", Instant.now());
            
            return ResponseEntity.ok(result);
            
        } catch (Exception e) {
            result.put("status", "error");
            result.put("message", "Mapper Bean 检查失败: " + e.getMessage());
            result.put("timestamp", Instant.now());
            
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(result);
        }
    }
    
    /**
     * 🔥 测试映射功能
     */
    @PostMapping("/test-mapping")
    public ResponseEntity<Map<String, Object>> testMapping() {
        Map<String, Object> result = new HashMap<>();
        
        try {
            troubleshooter.testMappingFunctionality();
            
            result.put("status", "success");
            result.put("message", "映射功能测试完成");
            result.put("timestamp", Instant.now());
            
            return ResponseEntity.ok(result);
            
        } catch (Exception e) {
            result.put("status", "error");
            result.put("message", "映射功能测试失败: " + e.getMessage());
            result.put("timestamp", Instant.now());
            
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(result);
        }
    }
    
    /**
     * 🔥 获取映射执行报告
     */
    @GetMapping("/execution-report/{traceId}")
    public ResponseEntity<MappingRuntimeDebugger.MappingExecutionReport> getExecutionReport(
            @PathVariable String traceId) {
        
        MappingRuntimeDebugger.MappingExecutionReport report = debugger.generateExecutionReport(traceId);
        
        if (report != null) {
            return ResponseEntity.ok(report);
        } else {
            return ResponseEntity.notFound().build();
        }
    }
    
    /**
     * 🔥 获取最近的映射错误
     */
    @GetMapping("/recent-errors")
    public ResponseEntity<List<MappingRuntimeDebugger.MappingError>> getRecentErrors(
            @RequestParam(defaultValue = "10") int limit) {
        
        // 这里需要在 MappingRuntimeDebugger 中添加获取最近错误的方法
        List<MappingRuntimeDebugger.MappingError> recentErrors = getRecentMappingErrors(limit);
        
        return ResponseEntity.ok(recentErrors);
    }
    
    /**
     * 🔥 性能诊断
     */
    @GetMapping("/performance")
    public ResponseEntity<Map<String, Object>> diagnosePerformance() {
        Map<String, Object> result = new HashMap<>();
        
        try {
            troubleshooter.diagnosePerformanceIssues();
            
            // 收集性能指标
            Runtime runtime = Runtime.getRuntime();
            Map<String, Object> memoryInfo = new HashMap<>();
            memoryInfo.put("maxMemory", runtime.maxMemory());
            memoryInfo.put("totalMemory", runtime.totalMemory());
            memoryInfo.put("freeMemory", runtime.freeMemory());
            memoryInfo.put("usedMemory", runtime.totalMemory() - runtime.freeMemory());
            
            result.put("status", "success");
            result.put("message", "性能诊断完成");
            result.put("memoryInfo", memoryInfo);
            result.put("timestamp", Instant.now());
            
            return ResponseEntity.ok(result);
            
        } catch (Exception e) {
            result.put("status", "error");
            result.put("message", "性能诊断失败: " + e.getMessage());
            result.put("timestamp", Instant.now());
            
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(result);
        }
    }
    
    /**
     * 🔥 编译时诊断
     */
    @GetMapping("/compile-diagnostics")
    public ResponseEntity<Map<String, Object>> compileTimeDiagnostics() {
        Map<String, Object> result = new HashMap<>();
        
        try {
            // 重定向系统输出到字符串
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            PrintStream originalOut = System.out;
            System.setOut(new PrintStream(baos));
            
            try {
                CompileTimeDiagnostics.generateDiagnosticReport();
            } finally {
                System.setOut(originalOut);
            }
            
            String diagnosticOutput = baos.toString();
            
            result.put("status", "success");
            result.put("message", "编译时诊断完成");
            result.put("diagnosticOutput", diagnosticOutput);
            result.put("timestamp", Instant.now());
            
            return ResponseEntity.ok(result);
            
        } catch (Exception e) {
            result.put("status", "error");
            result.put("message", "编译时诊断失败: " + e.getMessage());
            result.put("timestamp", Instant.now());
            
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(result);
        }
    }
    
    // 辅助方法
    private List<MappingRuntimeDebugger.MappingError> getRecentMappingErrors(int limit) {
        // 这里需要实现获取最近错误的逻辑
        return Collections.emptyList();
    }
}

🎬 效果演示:调试工具使用

启用调试模式

bash 复制代码
# 1. 编译时调试
mvn clean compile -Datlas.mapper.debug=true -Datlas.mapper.verbose=true

# 2. 运行时调试
java -jar your-app.jar --atlas.mapper.debug.enabled=true --atlas.mapper.debug.api.enabled=true

# 3. 查看生成的源码
ls -la target/generated-sources/annotations/

# 4. 查看调试日志
tail -f logs/application.log | grep "atlas.mapper"

使用调试 API

bash 复制代码
# 执行完整故障排查
curl http://localhost:8080/api/debug/troubleshoot

# 检查 Mapper Bean
curl http://localhost:8080/api/debug/mappers

# 测试映射功能
curl -X POST http://localhost:8080/api/debug/test-mapping

# 性能诊断
curl http://localhost:8080/api/debug/performance

# 编译时诊断
curl http://localhost:8080/api/debug/compile-diagnostics

# 获取最近错误
curl http://localhost:8080/api/debug/recent-errors?limit=5

调试输出示例

ini 复制代码
=== Atlas Mapper 调试报告 ===
处理轮次: 1
处理的注解: 2 个
发现的错误: 0 个
发现的警告: 1 个

--- 警告详情 ---
警告: 字段 'status' 未映射到目标对象
位置: UserMapper.toDto()

=== 调试报告结束 ===

=== Mapper Bean 检查 ===
找到 2 个 Mapper Bean:
- userMapper: UserMapperImpl (实现类)
  └─ 方法数量: 3
    └─ toDto
    └─ toDtoList
    └─ fromDto

=== 映射功能测试 ===
✓ UserMapper Bean 获取成功
✓ 测试用户创建成功: User{id=1, name='测试用户', email='test@example.com'}
✓ 映射执行成功: UserDto{id=1, name='测试用户', email='test@example.com'}
✓ 所有字段映射验证通过

❓ 常见问题

Q1: 注解处理器没有执行怎么办?

A: 检查以下几个方面:

bash 复制代码
# 1. 检查依赖配置
mvn dependency:tree | grep atlas-mapper-processor

# 2. 检查编译器配置
mvn help:effective-pom | grep -A 20 maven-compiler-plugin

# 3. 强制重新编译
mvn clean compile -X

# 4. 检查生成的文件
find target -name "*MapperImpl.java"

Q2: 映射方法找不到怎么办?

A: 调试步骤:

java 复制代码
// 1. 检查接口定义
@Mapper(componentModel = "spring")
public interface UserMapper {
    UserDto toDto(User user);  // 确保方法签名正确
}

// 2. 检查生成的实现类
// target/generated-sources/annotations/.../UserMapperImpl.java

// 3. 检查 Spring Bean 注册
@Autowired
private ApplicationContext context;

public void checkBean() {
    try {
        UserMapper mapper = context.getBean(UserMapper.class);
        System.out.println("Bean found: " + mapper.getClass().getName());
    } catch (NoSuchBeanDefinitionException e) {
        System.out.println("Bean not found: " + e.getMessage());
    }
}

Q3: 类型转换失败怎么调试?

A: 类型转换调试技巧:

java 复制代码
// 1. 启用详细日志
logging.level.io.github.nemoob.atlas.mapper=DEBUG

// 2. 添加调试断点
@Mapper
public interface UserMapper {
    @Mapping(target = "createdAt", source = "createdAt", qualifiedByName = "formatDateTime")
    UserDto toDto(User user);
    
    @Named("formatDateTime")
    default String formatDateTime(LocalDateTime dateTime) {
        System.out.println("Converting: " + dateTime);  // 调试输出
        return dateTime != null ? dateTime.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME) : null;
    }
}

// 3. 使用类型转换调试器
debugger.debugTypeConversion(sourceValue, targetValue, "formatDateTime");

Q4: 性能问题如何定位?

A: 性能问题定位方法:

java 复制代码
// 1. 使用性能监控
@Around("@within(io.github.nemoob.atlas.mapper.Mapper)")
public Object monitorPerformance(ProceedingJoinPoint joinPoint) throws Throwable {
    long start = System.nanoTime();
    try {
        return joinPoint.proceed();
    } finally {
        long duration = System.nanoTime() - start;
        if (duration > 10_000_000) {  // 超过 10ms
            log.warn("慢映射: {}.{} 耗时 {:.2f}ms", 
                joinPoint.getTarget().getClass().getSimpleName(),
                joinPoint.getSignature().getName(),
                duration / 1_000_000.0);
        }
    }
}

// 2. 使用 JProfiler 或 VisualVM 进行性能分析

// 3. 检查内存使用
Runtime runtime = Runtime.getRuntime();
long before = runtime.totalMemory() - runtime.freeMemory();
// 执行映射
long after = runtime.totalMemory() - runtime.freeMemory();
System.out.println("内存使用: " + (after - before) + " bytes");

🎯 本章小结

通过本章学习,你应该掌握了:

  1. 编译时调试:注解处理器调试和依赖冲突诊断
  2. 运行时调试:映射执行监控和错误分析
  3. 性能调试:性能问题定位和优化建议
  4. 调试工具:完整的调试工具链和 API

📖 下一步学习

在下一篇教程中,我们将学习:

  • 项目打包和发布流程
  • Maven 仓库发布配置
  • Docker 容器化部署
  • 生产环境部署最佳实践
相关推荐
维天说1 小时前
CLI-Switch 2026年3月版历史设计:Hook、TTY 隔离与 JSON 状态
java·服务器·json
Zane19942 小时前
并发 vs 并行:别再傻傻分不清了,一文讲透 Java 并发编程的第一课
java·后端
用户84913717547162 小时前
想做护眼工具却脑子一片空白?我用 OpenSpec 把模糊想法聊成了 v0.1
github·vibecoding
wangruofeng2 小时前
git-filter-repo 把 .git 从 112MB 砍到 1.4MB,但漏推 tag 让 clone 又胖回来
github·devops
杨充2 小时前
11.DDD与战术建模
设计模式·开源·代码规范
杨充3 小时前
12.综合实战图片框架
设计模式·开源·代码规范
噢,我明白了3 小时前
java中Excel的导入和导出(EasyExcel)
java·开发语言·excel
吠品3 小时前
Zabbix Web界面误报Server未运行的排查与解决
java·服务器·数据库
啊湘3 小时前
天气查询API接口 按月Token鉴权 实时天气 物联网可用 文档齐全
java·后端·struts
峰向AI3 小时前
Block 放出大招!Buzz:一个中继统一代码、聊天、CI 全流程
github