概述

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


️ 映射器架构设计

映射器层次结构图

classDiagram
    class BaseMapper {
        <<interface>>
        +mapAuditInfo(AuditInfo) AuditInfoDto
        +mapAddress(Address) AddressDto
        +getCurrentTenantId() Long
    }
    
    class OrderAggregateMapper {
        <<interface>>
        +toDto(OrderAggregate) OrderAggregateDto
        +toQueryDto(OrderAggregate) OrderQueryDto
        +toSummaryDto(OrderAggregate) OrderSummaryDto
        +toDtoList(List~OrderAggregate~) List~OrderAggregateDto~
        +toDtoPage(Page~OrderAggregate~) PageResponseDto~OrderAggregateDto~
    }
    
    class CustomerMapper {
        <<interface>>
        +toDto(Customer) CustomerDto
        +toSummaryDto(Customer) CustomerSummaryDto
        +fromCreateRequest(CustomerCreateRequest) Customer
        +updateFromRequest(CustomerUpdateRequest, Customer) Customer
    }
    
    class ProductMapper {
        <<interface>>
        +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. 基础映射器接口

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. 订单聚合根映射器

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. 动态映射引擎

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. 高性能批量映射器

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

性能监控和指标收集

映射性能监控器

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

配置和扩展

映射器配置类

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. 代码质量保证

  • 单元测试:全面的测试覆盖
  • 集成测试:端到端的功能验证
  • 性能测试:压力测试和基准测试
  • 代码审查:严格的代码质量控制
本站提供的所有下载资源均来自互联网,仅提供学习交流使用,版权归原作者所有。如需商业使用,请联系原作者获得授权。 如您发现有涉嫌侵权的内容,请联系我们 邮箱:[email protected]