CleanArchitecture职责链:请求处理流水线
在现代企业级应用开发中,请求处理往往涉及多个横切关注点(Cross-Cutting Concerns),如日志记录、缓存、验证、授权等。传统的做法是在每个处理程序中重复这些逻辑,导致代码冗余和维护困难。CleanArchitecture通过MediatR的`IPipelineBehavior`接口实现了职责链模式,构建了一个灵活、可扩展的请求处理流水线...
·
CleanArchitecture职责链:请求处理流水线
引言:为什么需要职责链模式?
在现代企业级应用开发中,请求处理往往涉及多个横切关注点(Cross-Cutting Concerns),如日志记录、缓存、验证、授权等。传统的做法是在每个处理程序中重复这些逻辑,导致代码冗余和维护困难。
CleanArchitecture通过MediatR的IPipelineBehavior<TRequest, TResponse>接口实现了职责链模式,构建了一个灵活、可扩展的请求处理流水线。本文将深入解析这一机制的设计原理和实现细节。
职责链模式的核心组件
1. 管道行为接口 (IPipelineBehavior)
public interface IPipelineBehavior<TRequest, TResponse>
where TRequest : IRequest<TResponse>
{
Task<TResponse> Handle(TRequest request,
RequestHandlerDelegate<TResponse> next,
CancellationToken cancellationToken);
}
2. 缓存行为实现 (CachingBehavior)
public class CachingBehavior<TRequest, TResponse> :
IPipelineBehavior<TRequest, TResponse?>
where TRequest : IRequest<TResponse>
{
private readonly IMemoryCache _cache;
private readonly ILogger<Mediator> _logger;
public async Task<TResponse?> Handle(TRequest request,
RequestHandlerDelegate<TResponse?> next,
CancellationToken cancellationToken)
{
var cacheKey = request.GetType().FullName ?? "";
return await _cache.GetOrCreateAsync(cacheKey, async entry =>
{
_logger.LogInformation($"Cache miss. Getting data from database. ({cacheKey})");
entry.SetOptions(_cacheOptions);
return await next();
});
}
}
3. 日志行为实现 (LoggingBehavior)
public class LoggingBehavior<TRequest, TResponse> :
IPipelineBehavior<TRequest, TResponse>
where TRequest : IRequest<TResponse>
{
private readonly ILogger<LoggingBehavior<TRequest, TResponse>> _logger;
public async Task<TResponse> Handle(TRequest request,
RequestHandlerDelegate<TResponse> next,
CancellationToken cancellationToken)
{
_logger.LogInformation($"Handling {typeof(TRequest).Name}");
var response = await next();
_logger.LogInformation($"Handled {typeof(TRequest).Name}");
return response;
}
}
配置管道行为
MediatR配置类
public static class MediatrConfig
{
public static IServiceCollection AddMediatrConfigs(this IServiceCollection services)
{
var mediatRAssemblies = new[]
{
Assembly.GetAssembly(typeof(Contributor)), // Core
Assembly.GetAssembly(typeof(CreateContributorCommand)), // UseCases
Assembly.GetAssembly(typeof(InfrastructureServiceExtensions)) // Infrastructure
};
services.AddMediatR(cfg => cfg.RegisterServicesFromAssemblies(mediatRAssemblies!))
.AddScoped(typeof(IPipelineBehavior<,>), typeof(LoggingBehavior<,>))
.AddScoped(typeof(IPipelineBehavior<,>), typeof(CachingBehavior<,>))
.AddScoped<IDomainEventDispatcher, MediatRDomainEventDispatcher>();
return services;
}
}
职责链执行流程
请求处理时序图
管道行为执行顺序表
| 执行顺序 | 行为类型 | 主要职责 | 是否可跳过后续处理 |
|---|---|---|---|
| 1 | LoggingBehavior | 记录请求开始日志 | 否 |
| 2 | CachingBehavior | 检查缓存,命中则直接返回 | 是(缓存命中时) |
| 3 | ValidationBehavior | 请求参数验证 | 是(验证失败时) |
| 4 | AuthorizationBehavior | 权限检查 | 是(无权限时) |
| 5 | Main Handler | 核心业务逻辑处理 | 否 |
自定义管道行为开发指南
1. 性能监控行为
public class PerformanceBehavior<TRequest, TResponse> :
IPipelineBehavior<TRequest, TResponse>
{
private readonly ILogger<PerformanceBehavior<TRequest, TResponse>> _logger;
private readonly Stopwatch _timer;
public PerformanceBehavior(ILogger<PerformanceBehavior<TRequest, TResponse>> logger)
{
_logger = logger;
_timer = new Stopwatch();
}
public async Task<TResponse> Handle(TRequest request,
RequestHandlerDelegate<TResponse> next,
CancellationToken cancellationToken)
{
_timer.Start();
var response = await next();
_timer.Stop();
var elapsedMilliseconds = _timer.ElapsedMilliseconds;
if (elapsedMilliseconds > 500)
{
_logger.LogWarning($"Long Running Request: {typeof(TRequest).Name} " +
$"({elapsedMilliseconds} milliseconds)");
}
return response;
}
}
2. 异常处理行为
public class ExceptionHandlingBehavior<TRequest, TResponse> :
IPipelineBehavior<TRequest, TResponse>
where TRequest : IRequest<TResponse>
{
private readonly ILogger<ExceptionHandlingBehavior<TRequest, TResponse>> _logger;
public async Task<TResponse> Handle(TRequest request,
RequestHandlerDelegate<TResponse> next,
CancellationToken cancellationToken)
{
try
{
return await next();
}
catch (Exception ex)
{
var requestName = typeof(TRequest).Name;
_logger.LogError(ex, $"Request: {requestName} failed");
throw new CustomException($"Request {requestName} failed", ex);
}
}
}
最佳实践与注意事项
1. 行为注册顺序的重要性
管道行为的执行顺序与注册顺序一致,需要谨慎安排:
// 正确的注册顺序
services.AddScoped(typeof(IPipelineBehavior<,>), typeof(LoggingBehavior<,>))
.AddScoped(typeof(IPipelineBehavior<,>), typeof(ValidationBehavior<,>))
.AddScoped(typeof(IPipelineBehavior<,>), typeof(AuthorizationBehavior<,>))
.AddScoped(typeof(IPipelineBehavior<,>), typeof(CachingBehavior<,>));
2. 性能优化建议
- 缓存行为应尽早执行以减少不必要的处理
- 验证和授权行为应在业务逻辑之前执行
- 日志行为应包裹整个处理流程
3. 条件性管道行为
对于需要条件执行的管道行为,可以使用装饰器模式:
public class ConditionalCachingBehavior<TRequest, TResponse> :
IPipelineBehavior<TRequest, TResponse>
where TRequest : IRequest<TResponse>
{
private readonly IMemoryCache _cache;
private readonly ICachePolicy<TRequest> _cachePolicy;
public async Task<TResponse> Handle(TRequest request,
RequestHandlerDelegate<TResponse> next,
CancellationToken cancellationToken)
{
if (!_cachePolicy.ShouldCache(request))
{
return await next();
}
// 缓存逻辑...
}
}
总结
CleanArchitecture的职责链模式通过MediatR的管道行为机制,实现了高度可扩展的请求处理流水线。这种设计模式带来了以下优势:
- 关注点分离:每个管道行为只负责单一功能
- 代码复用:横切关注点可以在多个处理程序间共享
- 灵活扩展:可以轻松添加新的管道行为而不影响现有代码
- 执行顺序可控:通过注册顺序控制行为执行流程
通过合理设计管道行为,开发者可以构建出既保持Clean Architecture原则,又具备强大横切关注点处理能力的企业级应用系统。
更多推荐


所有评论(0)