学习目标

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

  • 掌握 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:编译时调试工具

注解处理器调试配置

/**
 * 调试增强的注解处理器
 */
@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 调试配置

<!-- 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:运行时调试工具

映射执行监控器

/**
 * 运行时映射监控和调试工具
 */
@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. 检查源对象是否为 nulln2. 使用 @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 切面

/**
 * 映射调试切面
 */
@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:编译时问题诊断

/**
 * 编译时问题诊断工具
 */
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:运行时问题排查

/**
 * 运行时问题排查工具
 */
@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("[email protected]");
        user.setCreatedAt(LocalDateTime.now());
        user.setUpdatedAt(LocalDateTime.now());
        return user;
    }
}

示例 3:调试 REST API

/**
 * 调试和故障排查 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();
    }
}

效果演示:调试工具使用

启用调试模式

# 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

# 执行完整故障排查
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

调试输出示例

=== 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='[email protected]'}
 映射执行成功: UserDto{id=1, name='测试用户', email='[email protected]'}
 所有字段映射验证通过

常见问题

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

A: 检查以下几个方面:

# 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: 调试步骤:

// 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: 类型转换调试技巧:

// 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: 性能问题定位方法:

// 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 容器化部署
  • 生产环境部署最佳实践
本站提供的所有下载资源均来自互联网,仅提供学习交流使用,版权归原作者所有。如需商业使用,请联系原作者获得授权。 如您发现有涉嫌侵权的内容,请联系我们 邮箱:[email protected]