案例03-附件B-映射器实现

📋 概述

本文档详细描述了如何使用 Atlas Mapper 实现复杂的企业级映射器,包括循环引用处理、性能优化、动态规则引擎和多租户支持等高级功能。


🏗️ 映射器架构设计

映射器层次结构图

classDiagram class BaseMapper { <> +mapAuditInfo(AuditInfo) AuditInfoDto +mapAddress(Address) AddressDto +getCurrentTenantId() Long } class OrderAggregateMapper { <> +toDto(OrderAggregate) OrderAggregateDto +toQueryDto(OrderAggregate) OrderQueryDto +toSummaryDto(OrderAggregate) OrderSummaryDto +toDtoList(List~OrderAggregate~) List~OrderAggregateDto~ +toDtoPage(Page~OrderAggregate~) PageResponseDto~OrderAggregateDto~ } class CustomerMapper { <> +toDto(Customer) CustomerDto +toSummaryDto(Customer) CustomerSummaryDto +fromCreateRequest(CustomerCreateRequest) Customer +updateFromRequest(CustomerUpdateRequest, Customer) Customer } class ProductMapper { <> +toDto(Product) ProductDto +toSummaryDto(Product) ProductSummaryDto +toCatalogDto(Product) ProductCatalogDto } class DynamicMappingEngine { +applyTenantRules(Object, Object, Long) +applyFieldMappingRules(Object, Object, String) +validateMappingResult(Object) ValidationResult } BaseMapper <|-- OrderAggregateMapper BaseMapper <|-- CustomerMapper BaseMapper <|-- ProductMapper OrderAggregateMapper --> CustomerMapper OrderAggregateMapper --> ProductMapper OrderAggregateMapper --> DynamicMappingEngine

🔧 核心映射器实现

1. 基础映射器接口

java 复制代码
package io.github.nemoob.atlas.mapper.example.mapper;

import io.github.nemoob.atlas.mapper.Mapper;
import io.github.nemoob.atlas.mapper.Mapping;
import io.github.nemoob.atlas.mapper.example.domain.AuditInfo;
import io.github.nemoob.atlas.mapper.example.domain.Address;
import io.github.nemoob.atlas.mapper.example.dto.AuditInfoDto;
import io.github.nemoob.atlas.mapper.example.dto.AddressDto;
import org.springframework.security.core.context.SecurityContextHolder;

/**
 * 基础映射器 - 提供通用映射方法和租户上下文
 */
@Mapper(componentModel = "spring")
public interface BaseMapper {
    
    /**
     * 映射审计信息
     */
    @Mapping(target = "createdTimeFormatted", 
             expression = "java(formatDateTime(auditInfo.getCreatedTime()))")
    @Mapping(target = "updatedTimeFormatted", 
             expression = "java(formatDateTime(auditInfo.getUpdatedTime()))")
    AuditInfoDto mapAuditInfo(AuditInfo auditInfo);
    
    /**
     * 映射地址信息
     */
    @Mapping(target = "fullAddress", expression = "java(address.getFullAddress())")
    @Mapping(target = "isComplete", expression = "java(address.isComplete())")
    AddressDto mapAddress(Address address);
    
    /**
     * 获取当前租户ID
     */
    default Long getCurrentTenantId() {
        // 从安全上下文获取当前租户ID
        return SecurityContextHolder.getContext()
            .getAuthentication()
            .getPrincipal() instanceof TenantAwarePrincipal principal 
            ? principal.getTenantId() 
            : 1L; // 默认租户
    }
    
    /**
     * 格式化日期时间
     */
    default String formatDateTime(java.time.LocalDateTime dateTime) {
        return dateTime != null 
            ? dateTime.format(java.time.format.DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))
            : null;
    }
    
    /**
     * 格式化金额
     */
    default String formatAmount(java.math.BigDecimal amount) {
        return amount != null 
            ? String.format("¥%,.2f", amount)
            : "¥0.00";
    }
    
    /**
     * 计算百分比
     */
    default String formatPercentage(java.math.BigDecimal rate) {
        return rate != null 
            ? String.format("%.2f%%", rate.multiply(java.math.BigDecimal.valueOf(100)))
            : "0.00%";
    }
}

2. 订单聚合根映射器

java 复制代码
package io.github.nemoob.atlas.mapper.example.mapper;

import io.github.nemoob.atlas.mapper.Mapper;
import io.github.nemoob.atlas.mapper.Mapping;
import io.github.nemoob.atlas.mapper.Named;
import io.github.nemoob.atlas.mapper.example.domain.OrderAggregate;
import io.github.nemoob.atlas.mapper.example.domain.OrderLine;
import io.github.nemoob.atlas.mapper.example.dto.*;
import org.springframework.data.domain.Page;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.List;
import java.util.stream.Collectors;

/**
 * 订单聚合根映射器 - 处理复杂的订单对象映射
 */
@Mapper(componentModel = "spring", uses = {CustomerMapper.class, ProductMapper.class})
public abstract class OrderAggregateMapper implements BaseMapper {
    
    @Autowired
    protected DynamicMappingEngine dynamicMappingEngine;
    
    @Autowired
    protected TenantConfigService tenantConfigService;
    
    /**
     * 完整订单映射 - 用于详情页面
     */
    @Mapping(target = "statusDescription", 
             expression = "java(order.getStatus().getDescription())")
    @Mapping(target = "customer", source = "customer", qualifiedByName = "mapCustomerSummary")
    @Mapping(target = "lines", source = "lines", qualifiedByName = "mapOrderLines")
    @Mapping(target = "totalLines", expression = "java(order.getLines().size())")
    @Mapping(target = "averageLineAmount", 
             expression = "java(calculateAverageLineAmount(order.getLines()))")
    @Mapping(target = "canBeCancelled", expression = "java(order.canBeCancelled())")
    @Mapping(target = "isCompleted", expression = "java(order.isCompleted())")
    public abstract OrderAggregateDto toDto(OrderAggregate order);
    
    /**
     * 查询列表映射 - 用于列表页面(性能优化版本)
     */
    @Mapping(target = "customerName", source = "customer.companyName")
    @Mapping(target = "customerCode", source = "customer.customerCode")
    @Mapping(target = "totalLines", expression = "java(order.getLines().size())")
    @Mapping(target = "createdTime", source = "auditInfo.createdTime")
    @Mapping(target = "createdBy", source = "auditInfo.createdBy")
    public abstract OrderQueryDto toQueryDto(OrderAggregate order);
    
    /**
     * 摘要映射 - 用于仪表板和报表
     */
    @Mapping(target = "customerName", source = "customer.companyName")
    @Mapping(target = "lineCount", expression = "java(order.getLines().size())")
    @Mapping(target = "statusDescription", 
             expression = "java(order.getStatus().getDescription())")
    public abstract OrderSummaryDto toSummaryDto(OrderAggregate order);
    
    /**
     * 批量映射 - 性能优化的批量处理
     */
    public List<OrderAggregateDto> toDtoList(List<OrderAggregate> orders) {
        return orders.parallelStream()
            .map(this::toDto)
            .collect(Collectors.toList());
    }
    
    /**
     * 分页映射 - 处理分页结果
     */
    public PageResponseDto<OrderAggregateDto> toDtoPage(Page<OrderAggregate> page) {
        PageResponseDto<OrderAggregateDto> result = new PageResponseDto<>();
        result.setContent(toDtoList(page.getContent()));
        result.setPageNumber(page.getNumber());
        result.setPageSize(page.getSize());
        result.setTotalElements(page.getTotalElements());
        result.setTotalPages(page.getTotalPages());
        result.setFirst(page.isFirst());
        result.setLast(page.isLast());
        result.setHasNext(page.hasNext());
        result.setHasPrevious(page.hasPrevious());
        return result;
    }
    
    /**
     * 客户摘要映射 - 避免循环引用
     */
    @Named("mapCustomerSummary")
    @Mapping(target = "type", expression = "java(customer.getType().getDescription())")
    @Mapping(target = "level", expression = "java(customer.getLevel().getDescription())")
    protected abstract CustomerSummaryDto mapCustomerSummary(
        io.github.nemoob.atlas.mapper.example.domain.Customer customer);
    
    /**
     * 订单行项目映射 - 处理嵌套集合
     */
    @Named("mapOrderLines")
    protected List<OrderLineDto> mapOrderLines(List<OrderLine> lines) {
        if (lines == null || lines.isEmpty()) {
            return List.of();
        }
        
        return lines.stream()
            .map(this::mapOrderLine)
            .collect(Collectors.toList());
    }
    
    /**
     * 单个订单行映射
     */
    @Mapping(target = "product", source = "product", qualifiedByName = "mapProductSummary")
    @Mapping(target = "isReserved", expression = "java(line.isReserved())")
    @Mapping(target = "reservationExpiry", 
             source = "reservation.expiryTime", 
             conditionExpression = "java(line.getReservation() != null)")
    protected abstract OrderLineDto mapOrderLine(OrderLine line);
    
    /**
     * 产品摘要映射
     */
    @Named("mapProductSummary")
    @Mapping(target = "status", expression = "java(product.getStatus().getDescription())")
    @Mapping(target = "currentPrice", expression = "java(product.getCurrentPrice())")
    @Mapping(target = "availableQuantity", 
             source = "inventory.availableQuantity",
             conditionExpression = "java(product.getInventory() != null)")
    protected abstract ProductSummaryDto mapProductSummary(
        io.github.nemoob.atlas.mapper.example.domain.Product product);
    
    /**
     * 计算平均行金额
     */
    protected java.math.BigDecimal calculateAverageLineAmount(List<OrderLine> lines) {
        if (lines == null || lines.isEmpty()) {
            return java.math.BigDecimal.ZERO;
        }
        
        java.math.BigDecimal total = lines.stream()
            .map(OrderLine::getLineAmount)
            .reduce(java.math.BigDecimal.ZERO, java.math.BigDecimal::add);
            
        return total.divide(
            java.math.BigDecimal.valueOf(lines.size()), 
            2, 
            java.math.RoundingMode.HALF_UP
        );
    }
    
    /**
     * 后处理 - 应用动态规则和租户配置
     */
    @org.mapstruct.AfterMapping
    protected void applyDynamicRules(OrderAggregate source, @org.mapstruct.MappingTarget OrderAggregateDto target) {
        // 应用租户特定的映射规则
        Long tenantId = getCurrentTenantId();
        dynamicMappingEngine.applyTenantRules(source, target, tenantId);
        
        // 应用字段级别的动态规则
        TenantConfig config = tenantConfigService.getTenantConfig(tenantId);
        if (config.isHideCustomerInfo()) {
            target.setCustomer(null);
        }
        
        if (config.isHidePricingInfo()) {
            target.setTotalAmount(null);
            target.setTaxAmount(null);
            target.getLines().forEach(line -> {
                line.setUnitPrice(null);
                line.setLineAmount(null);
            });
        }
        
        // 应用数据脱敏规则
        applyDataMasking(target, config);
    }
    
    /**
     * 数据脱敏处理
     */
    private void applyDataMasking(OrderAggregateDto target, TenantConfig config) {
        if (config.isMaskCustomerInfo() && target.getCustomer() != null) {
            CustomerSummaryDto customer = target.getCustomer();
            if (customer.getContactPerson() != null) {
                customer.setContactPerson(maskName(customer.getContactPerson()));
            }
        }
    }
    
    /**
     * 姓名脱敏
     */
    private String maskName(String name) {
        if (name == null || name.length() <= 1) {
            return name;
        }
        return name.charAt(0) + "*".repeat(name.length() - 1);
    }
}

3. 动态映射引擎

java 复制代码
package io.github.nemoob.atlas.mapper.example.engine;

import org.springframework.stereotype.Component;
import org.springframework.beans.factory.annotation.Autowired;
import lombok.extern.slf4j.Slf4j;

import java.lang.reflect.Field;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 动态映射引擎 - 支持运行时配置的映射规则
 */
@Component
@Slf4j
public class DynamicMappingEngine {
    
    @Autowired
    private MappingRuleRepository ruleRepository;
    
    @Autowired
    private TenantConfigService tenantConfigService;
    
    // 规则缓存
    private final Map<String, MappingRule> ruleCache = new ConcurrentHashMap<>();
    
    /**
     * 应用租户特定的映射规则
     */
    public void applyTenantRules(Object source, Object target, Long tenantId) {
        try {
            String ruleKey = buildRuleKey(source.getClass(), target.getClass(), tenantId);
            MappingRule rule = getRuleFromCache(ruleKey);
            
            if (rule != null) {
                rule.apply(source, target);
                log.debug("Applied tenant rule {} for tenant {}", ruleKey, tenantId);
            }
        } catch (Exception e) {
            log.error("Error applying tenant rules for tenant {}: {}", tenantId, e.getMessage(), e);
        }
    }
    
    /**
     * 应用字段级别的映射规则
     */
    public void applyFieldMappingRules(Object source, Object target, String fieldName) {
        try {
            String ruleKey = buildFieldRuleKey(source.getClass(), target.getClass(), fieldName);
            FieldMappingRule rule = getFieldRuleFromCache(ruleKey);
            
            if (rule != null) {
                rule.apply(source, target, fieldName);
                log.debug("Applied field rule {} for field {}", ruleKey, fieldName);
            }
        } catch (Exception e) {
            log.error("Error applying field rules for field {}: {}", fieldName, e.getMessage(), e);
        }
    }
    
    /**
     * 验证映射结果
     */
    public ValidationResult validateMappingResult(Object target) {
        ValidationResult result = new ValidationResult();
        
        try {
            // 基础验证
            if (target == null) {
                result.addError("Target object is null");
                return result;
            }
            
            // 字段验证
            validateRequiredFields(target, result);
            validateFieldConstraints(target, result);
            validateBusinessRules(target, result);
            
        } catch (Exception e) {
            result.addError("Validation error: " + e.getMessage());
            log.error("Error validating mapping result: {}", e.getMessage(), e);
        }
        
        return result;
    }
    
    /**
     * 从缓存获取规则
     */
    private MappingRule getRuleFromCache(String ruleKey) {
        return ruleCache.computeIfAbsent(ruleKey, key -> {
            try {
                return ruleRepository.findByKey(key);
            } catch (Exception e) {
                log.warn("Failed to load rule {}: {}", key, e.getMessage());
                return null;
            }
        });
    }
    
    /**
     * 从缓存获取字段规则
     */
    private FieldMappingRule getFieldRuleFromCache(String ruleKey) {
        // 实现字段规则缓存逻辑
        return null; // 简化实现
    }
    
    /**
     * 构建规则键
     */
    private String buildRuleKey(Class<?> sourceClass, Class<?> targetClass, Long tenantId) {
        return String.format("%s->%s:tenant_%d", 
            sourceClass.getSimpleName(), 
            targetClass.getSimpleName(), 
            tenantId);
    }
    
    /**
     * 构建字段规则键
     */
    private String buildFieldRuleKey(Class<?> sourceClass, Class<?> targetClass, String fieldName) {
        return String.format("%s->%s:field_%s", 
            sourceClass.getSimpleName(), 
            targetClass.getSimpleName(), 
            fieldName);
    }
    
    /**
     * 验证必填字段
     */
    private void validateRequiredFields(Object target, ValidationResult result) {
        Class<?> clazz = target.getClass();
        Field[] fields = clazz.getDeclaredFields();
        
        for (Field field : fields) {
            if (field.isAnnotationPresent(javax.validation.constraints.NotNull.class)) {
                field.setAccessible(true);
                try {
                    Object value = field.get(target);
                    if (value == null) {
                        result.addError(String.format("Required field '%s' is null", field.getName()));
                    }
                } catch (IllegalAccessException e) {
                    log.warn("Cannot access field {}: {}", field.getName(), e.getMessage());
                }
            }
        }
    }
    
    /**
     * 验证字段约束
     */
    private void validateFieldConstraints(Object target, ValidationResult result) {
        // 实现字段约束验证逻辑
        // 例如:长度限制、数值范围、格式验证等
    }
    
    /**
     * 验证业务规则
     */
    private void validateBusinessRules(Object target, ValidationResult result) {
        // 实现业务规则验证逻辑
        // 例如:订单金额不能为负数、客户状态检查等
    }
}

/**
 * 映射规则接口
 */
public interface MappingRule {
    void apply(Object source, Object target);
    String getRuleKey();
    boolean isActive();
}

/**
 * 字段映射规则接口
 */
public interface FieldMappingRule {
    void apply(Object source, Object target, String fieldName);
    String getFieldName();
    boolean isActive();
}

/**
 * 验证结果类
 */
@lombok.Data
public class ValidationResult {
    private boolean valid = true;
    private java.util.List<String> errors = new java.util.ArrayList<>();
    private java.util.List<String> warnings = new java.util.ArrayList<>();
    
    public void addError(String error) {
        this.errors.add(error);
        this.valid = false;
    }
    
    public void addWarning(String warning) {
        this.warnings.add(warning);
    }
    
    public boolean hasErrors() {
        return !errors.isEmpty();
    }
    
    public boolean hasWarnings() {
        return !warnings.isEmpty();
    }
}

4. 高性能批量映射器

java 复制代码
package io.github.nemoob.atlas.mapper.example.mapper;

import org.springframework.stereotype.Service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ForkJoinPool;
import java.util.stream.Collectors;

/**
 * 高性能批量映射服务
 */
@Service
public class BatchMappingService {
    
    @Autowired
    private OrderAggregateMapper orderMapper;
    
    @Autowired
    private MappingMetricsCollector metricsCollector;
    
    // 自定义线程池用于并行处理
    private final ForkJoinPool customThreadPool = new ForkJoinPool(
        Runtime.getRuntime().availableProcessors() * 2
    );
    
    /**
     * 高性能批量映射 - 使用并行流和分批处理
     */
    @Transactional(readOnly = true)
    public List<OrderAggregateDto> batchMapOrders(List<OrderAggregate> orders) {
        long startTime = System.currentTimeMillis();
        
        try {
            // 分批处理,避免内存溢出
            int batchSize = calculateOptimalBatchSize(orders.size());
            
            List<OrderAggregateDto> result = orders.stream()
                .collect(Collectors.groupingBy(order -> orders.indexOf(order) / batchSize))
                .values()
                .parallelStream()
                .flatMap(batch -> processBatch(batch).stream())
                .collect(Collectors.toList());
                
            // 记录性能指标
            long duration = System.currentTimeMillis() - startTime;
            metricsCollector.recordBatchMapping(orders.size(), duration);
            
            return result;
            
        } catch (Exception e) {
            metricsCollector.recordMappingError("batch_mapping", e);
            throw new MappingException("Batch mapping failed", e);
        }
    }
    
    /**
     * 异步批量映射
     */
    @Async
    public CompletableFuture<List<OrderAggregateDto>> batchMapOrdersAsync(List<OrderAggregate> orders) {
        return CompletableFuture.supplyAsync(() -> batchMapOrders(orders), customThreadPool);
    }
    
    /**
     * 流式映射 - 适用于超大数据集
     */
    public java.util.stream.Stream<OrderAggregateDto> streamMapOrders(
            java.util.stream.Stream<OrderAggregate> orderStream) {
        
        return orderStream
            .parallel()
            .map(order -> {
                try {
                    return orderMapper.toDto(order);
                } catch (Exception e) {
                    metricsCollector.recordMappingError("stream_mapping", e);
                    return null; // 或者返回默认值
                }
            })
            .filter(dto -> dto != null);
    }
    
    /**
     * 处理单个批次
     */
    private List<OrderAggregateDto> processBatch(List<OrderAggregate> batch) {
        return batch.parallelStream()
            .map(orderMapper::toDto)
            .collect(Collectors.toList());
    }
    
    /**
     * 计算最优批次大小
     */
    private int calculateOptimalBatchSize(int totalSize) {
        // 基于可用内存和CPU核心数计算最优批次大小
        int availableProcessors = Runtime.getRuntime().availableProcessors();
        long maxMemory = Runtime.getRuntime().maxMemory();
        long freeMemory = Runtime.getRuntime().freeMemory();
        
        // 简化的计算逻辑
        int baseBatchSize = Math.max(100, totalSize / (availableProcessors * 4));
        
        // 根据内存情况调整
        if (freeMemory < maxMemory * 0.3) {
            baseBatchSize = Math.min(baseBatchSize, 50);
        }
        
        return Math.min(baseBatchSize, 1000); // 最大批次限制
    }
}

/**
 * 映射异常类
 */
public class MappingException extends RuntimeException {
    public MappingException(String message) {
        super(message);
    }
    
    public MappingException(String message, Throwable cause) {
        super(message, cause);
    }
}

📊 性能监控和指标收集

映射性能监控器

java 复制代码
package io.github.nemoob.atlas.mapper.example.monitoring;

import io.micrometer.core.instrument.MeterRegistry;
import io.micrometer.core.instrument.Timer;
import io.micrometer.core.instrument.Counter;
import org.springframework.stereotype.Component;
import org.springframework.beans.factory.annotation.Autowired;
import lombok.extern.slf4j.Slf4j;

/**
 * 映射指标收集器
 */
@Component
@Slf4j
public class MappingMetricsCollector {
    
    @Autowired
    private MeterRegistry meterRegistry;
    
    // 性能计时器
    private final Timer mappingTimer;
    private final Timer batchMappingTimer;
    
    // 错误计数器
    private final Counter mappingErrorCounter;
    private final Counter validationErrorCounter;
    
    public MappingMetricsCollector(MeterRegistry meterRegistry) {
        this.meterRegistry = meterRegistry;
        
        this.mappingTimer = Timer.builder("atlas.mapper.mapping.duration")
            .description("Time taken for object mapping")
            .register(meterRegistry);
            
        this.batchMappingTimer = Timer.builder("atlas.mapper.batch.duration")
            .description("Time taken for batch mapping")
            .register(meterRegistry);
            
        this.mappingErrorCounter = Counter.builder("atlas.mapper.errors")
            .description("Number of mapping errors")
            .register(meterRegistry);
            
        this.validationErrorCounter = Counter.builder("atlas.mapper.validation.errors")
            .description("Number of validation errors")
            .register(meterRegistry);
    }
    
    /**
     * 记录单个映射性能
     */
    public void recordMapping(String mappingType, long durationMs) {
        mappingTimer.record(durationMs, java.util.concurrent.TimeUnit.MILLISECONDS);
        
        // 记录详细标签
        Timer.Sample sample = Timer.start(meterRegistry);
        sample.stop(Timer.builder("atlas.mapper.mapping.detailed")
            .tag("type", mappingType)
            .register(meterRegistry));
    }
    
    /**
     * 记录批量映射性能
     */
    public void recordBatchMapping(int batchSize, long durationMs) {
        batchMappingTimer.record(durationMs, java.util.concurrent.TimeUnit.MILLISECONDS);
        
        // 记录吞吐量
        double throughput = (double) batchSize / durationMs * 1000; // 每秒处理数量
        meterRegistry.gauge("atlas.mapper.throughput", throughput);
        
        log.info("Batch mapping completed: {} items in {}ms, throughput: {:.2f} items/sec", 
            batchSize, durationMs, throughput);
    }
    
    /**
     * 记录映射错误
     */
    public void recordMappingError(String errorType, Exception error) {
        mappingErrorCounter.increment();
        
        Counter.builder("atlas.mapper.errors.detailed")
            .tag("type", errorType)
            .tag("exception", error.getClass().getSimpleName())
            .register(meterRegistry)
            .increment();
            
        log.error("Mapping error of type {}: {}", errorType, error.getMessage(), error);
    }
    
    /**
     * 记录验证错误
     */
    public void recordValidationError(String validationType, String errorMessage) {
        validationErrorCounter.increment();
        
        Counter.builder("atlas.mapper.validation.errors.detailed")
            .tag("type", validationType)
            .register(meterRegistry)
            .increment();
            
        log.warn("Validation error of type {}: {}", validationType, errorMessage);
    }
    
    /**
     * 记录内存使用情况
     */
    public void recordMemoryUsage() {
        Runtime runtime = Runtime.getRuntime();
        long totalMemory = runtime.totalMemory();
        long freeMemory = runtime.freeMemory();
        long usedMemory = totalMemory - freeMemory;
        
        meterRegistry.gauge("atlas.mapper.memory.used", usedMemory);
        meterRegistry.gauge("atlas.mapper.memory.free", freeMemory);
        meterRegistry.gauge("atlas.mapper.memory.total", totalMemory);
    }
}

🔧 配置和扩展

映射器配置类

java 复制代码
package io.github.nemoob.atlas.mapper.example.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Bean;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import java.util.concurrent.Executor;

/**
 * 映射器配置类
 */
@Configuration
@EnableAsync
public class MappingConfiguration {
    
    /**
     * 异步映射线程池
     */
    @Bean("mappingTaskExecutor")
    public Executor mappingTaskExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(4);
        executor.setMaxPoolSize(8);
        executor.setQueueCapacity(100);
        executor.setThreadNamePrefix("mapping-");
        executor.setRejectedExecutionHandler(new java.util.concurrent.ThreadPoolExecutor.CallerRunsPolicy());
        executor.initialize();
        return executor;
    }
    
    /**
     * 映射缓存配置
     */
    @Bean
    public org.springframework.cache.CacheManager mappingCacheManager() {
        org.springframework.cache.concurrent.ConcurrentMapCacheManager cacheManager = 
            new org.springframework.cache.concurrent.ConcurrentMapCacheManager();
        cacheManager.setCacheNames(java.util.Arrays.asList("mappingRules", "tenantConfigs"));
        return cacheManager;
    }
}

🎯 最佳实践总结

1. 性能优化策略

  • 并行处理:使用并行流和自定义线程池
  • 分批处理:避免大数据集导致的内存问题
  • 缓存机制:缓存映射规则和配置信息
  • 懒加载:按需加载关联对象

2. 错误处理和监控

  • 全面监控:记录性能指标和错误统计
  • 优雅降级:映射失败时的备用策略
  • 日志记录:详细的调试和错误日志
  • 告警机制:性能异常时的自动告警

3. 扩展性设计

  • 动态规则:支持运行时配置的映射规则
  • 多租户:租户隔离和个性化配置
  • 插件机制:支持自定义映射逻辑
  • 版本兼容:向后兼容的API设计

4. 代码质量保证

  • 单元测试:全面的测试覆盖
  • 集成测试:端到端的功能验证
  • 性能测试:压力测试和基准测试
  • 代码审查:严格的代码质量控制
相关推荐
杨杨杨大侠2 小时前
案例03-附件A-订单实体设计
java·开源·github
杨杨杨大侠2 小时前
案例03-附件C-性能优化
java·开源·github
杨杨杨大侠2 小时前
案例03-附件D-监控系统
java·开源·github
少女续续念3 小时前
国产 DevOps 崛起!Gitee 领衔构建合规、高效的企业协作工具链
git·开源
uhakadotcom3 小时前
什么是OpenTelemetry?
后端·面试·github
少女续续念5 小时前
AI 不再是 “旁观者”!Gitee MCP Server 让智能助手接管代码仓库管理
git·开源
华仔啊5 小时前
主线程存了用户信息,子线程居然拿不到?ThreadLocal 背锅
java·后端
间彧5 小时前
Spring Boot项目中,Redis 如何同时执行多条命令
java·redis