动手造轮子:实现一个简单的-AOP-框架,想搞定大厂面试官

MethodInfo ProxyMethod { get; }

object ProxyTarget { get; }

MethodInfo Method { get; }

object Target { get; }

object[] Arguments { get; }

Type[] GenericArguments { get; }

object ReturnValue { get; set; }

Dictionary<string, object> Properties { get; }

}

### IInterceptor

拦截器,用来定义公用的处理逻辑,方法拦截处理方法

接口定义如下:

public interface IInterceptor
{
Task Invoke(IInvocation invocation, Func next);
}

`invocation` 是方法执行的上下文,`next` 代表后续的逻辑处理,类似于 asp.net core 里的 `next` ,如果不想执行方面的方法不执行 `next` 逻辑即可

### IInterceptorResolver

用来根据当前的执行上下文获取到要执行的拦截器,默认是基于 FluentAPI 的实现,但是如果你特别想用基于 Attribute 的也是可以的,默认提供了一个 `AttributeInterceotorResovler`,你也可以自定义一个适合自己的 `InterceptorResolver`

public interface IInterceptorResolver
{
IReadOnlyList ResolveInterceptors(IInvocation invocation);
}

### IInvocationEnricher

上面 `IInvocation` 的定义中有一个用于扩展的 `Properties`,这个 `enricher` 主要就是基于 `Properties` 来丰富执行上下文信息的,比如说记录 `TraceId` 等请求链路追踪数据,构建方法执行链路等

public interface IEnricher
{
void Enrich(TContext context);
}
public interface IInvocationEnricher : IEnricher
{
}

### AspectDelegate

`AspectDelegate` 是用来将构建要执行的代理方法的方法体的,首先执行注册的 `InvocationEnricher`,丰富上下文信息,然后根据执行上下文获取要执行的拦截器,构建一个执行委托,生成委托使用了之前分享过的 `PipelineBuilder` 构建中间件模式的拦截器,执行拦截器逻辑

// apply enrichers
foreach (var enricher in FluentAspects.AspectOptions.Enrichers)
{
try
{
enricher.Enrich(invocation);
}
catch (Exception ex)
{
InvokeHelper.OnInvokeException?.Invoke(ex);
}
}

// get delegate
var builder = PipelineBuilder.CreateAsync(completeFunc);
foreach (var interceptor in interceptors)
{
builder.Use(interceptor.Invoke);
}
return builder.Build();

更多信息可以参考源码: [https://github.com/WeihanLi/WeihanLi.Common/blob/dev/src/WeihanLi.Common/Aspect/AspectDelegate.cs](https://gitee.com/vip204888/java-p7)

## 使用示例

推荐和依赖注入结合使用,主要分为以微软的注入框架为例,有两种使用方式,一种是手动注册代理服务,一种是自动批量注册代理服务,来看下面的实例就明白了

### 手动注册代理服务

使用方式一,手动注册代理服务:

为了方便使用,提供了一些 `AddProxy` 的扩展方法:

IServiceCollection services = new ServiceCollection();
services.AddFluentAspects(options =>
{
// 注册拦截器配置
options.NoInterceptProperty(f => f.Name);

    options.InterceptAll()
        .With<LogInterceptor>()
        ;
    options.InterceptMethod<DbContext>(x => x.Name == nameof(DbContext.SaveChanges)
                                            || x.Name == nameof(DbContext.SaveChangesAsync))
        .With<DbContextSaveInterceptor>()
        ;
    options.InterceptMethod<IFly>(f => f.Fly())
        .With<LogInterceptor>();
    options.InterceptType<IFly>()
        .With<LogInterceptor>();

    // 注册 InvocationEnricher
    options
        .WithProperty("TraceId", "121212")
        ;
});

// 使用 Castle 生成代理
services.AddFluentAspects(options =>
{
// 注册拦截器配置
options.NoInterceptProperty(f => f.Name);

    options.InterceptAll()
        .With<LogInterceptor>()
        ;
    options.InterceptMethod<DbContext>(x => x.Name == nameof(DbContext.SaveChanges)
                                            || x.Name == nameof(DbContext.SaveChangesAsync))
        .With<DbContextSaveInterceptor>()
        ;
    options.InterceptMethod<IFly>(f => f.Fly())
        .With<LogInterceptor>();
    options.InterceptType<IFly>()
        .With<LogInterceptor>();

    // 注册 InvocationEnricher
    options
        .WithProperty("TraceId", "121212")
        ;
}, builder => builder.UseCastle());

services.AddTransientProxy<IFly, MonkeyKing>();
services.AddSingletonProxy<IEventBus, EventBus>();
services.AddDbContext(options =>
{

面试资料整理汇总

成功从小公司跳槽进蚂蚁定级P7,只因刷了七遍这些面试真题

成功从小公司跳槽进蚂蚁定级P7,只因刷了七遍这些面试真题

这些面试题是我朋友进阿里前狂刷七遍以上的面试资料,由于面试文档很多,内容更多,没有办法一一为大家展示出来,所以只好为大家节选出来了一部分供大家参考,需要全部文档的,关注小编后,点击这里即可免费领取

面试的本质不是考试,而是告诉面试官你会做什么,所以,这些面试资料中提到的技术也是要学会的,不然稍微改动一下你就凉凉了

出来,所以只好为大家节选出来了一部分供大家参考,需要全部文档的,关注小编后,点击这里即可免费领取

面试的本质不是考试,而是告诉面试官你会做什么,所以,这些面试资料中提到的技术也是要学会的,不然稍微改动一下你就凉凉了

在这里祝大家能够拿到心仪的offer!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值