AOP 視頻講解 面向切麵編程AOP的對面向對象編程OOP的一個補充,它的特點是將系統邏輯和業務邏輯採取《非侵入式》分離。我們把系統封裝成一個一個的切麵(單一職責)進行順意編排組合,插入(織入)到業務邏輯的執行過程(織入點)。 系統邏輯:異常處理,身份認證,授權,mvc,數據校驗,事務處理。 業務邏 ...
AOP
視頻講解
面向切麵編程AOP的對面向對象編程OOP的一個補充,它的特點是將系統邏輯和業務邏輯採取《非侵入式》分離。我們把系統封裝成一個一個的切麵(單一職責)進行順意編排組合,插入(織入)到業務邏輯的執行過程(織入點)。
系統邏輯:異常處理,身份認證,授權,mvc,數據校驗,事務處理。
業務邏輯:就是我們的業務Service。
切麵:用於封裝系統邏輯,比如身份認證filter,或者中間件
切入點:就是管道的位置。名詞
織入:就是插入到管道的切入點的過程。動詞
AOP的特點:
1.非侵入式
2.低耦合
3.代碼服用
4.單一職責
5.可插拔
實現方式:
1.管道鏈,比如aspnetcore的中間件,mvc中的Filter
2.靜態代理:思考如何加強一個List,使得在插入時列印日誌?
3.動態代理:Emit
4.三種模式都需要通過一些技術進行串聯,實現鏈式調用,構成管道。靜態代理通過介面進行串聯,動態代理通過反射進行串聯。管道通過介面獲取委托進行串聯。委托本質也是介面。
代理:就是增強,代理對象必須儘量實現目標對象的功能,在此基礎上進行加強。比如vpn,你的電腦的網路就是目標對象,vpn就是代理服務,代理服務起碼得實現聯網功能吧,然後對網路進行加強,訪問到一些你的本機網路訪問不到的東西。
掌握了AOP技術我們可以實現很多好處,做到非侵入式的增強業務邏輯。
//侵入式方案,把這個看懂。後面就是圍繞這個開展,高出非侵入式
public static void A()
{
Console.WriteLine("A:開始");
B();//A,B的調用關係強行綁定,有侵入性
Console.WriteLine("A:結束");
}
public static void B()
{
Console.WriteLine("B:開始");
C();
Console.WriteLine("B:結束");
}
public static void C()
{
Console.WriteLine("Hello World");
}
public static void Dobasic()
{
A();
}
靜態代理
1.代理就是實現目標對象的標準(介面),在目標方法執行之前和之後進行邏輯織入的過程。代理的目的就是為了加強。代理不負責實現介面,一般通過target來實現介面。即代理除了可以增強之外還能簡化介面的實現。
2.靜態代理就是在代理之前就已經確定了代理關係。需要自己實現標準並編寫代理類。代理類中的邏輯只能代理一些標準(實現多個介面)。無法代理所有標準。
3.靜態代理可以實現不改變目標對象的源碼的情況下進行加強,完成目標對象的能力,並且在此基礎之上進行加強。
4.可以簡化實現的成本,不改變業務代碼,只需要編寫額外的增強邏輯。不需要關係具體的業務實現。
5.代理和代理直接通過介面可以進行互相代理,鏈式調用,順意編排組合,實現系統的多樣化。
/// <summary>
/// 定義標準1
/// </summary>
public interface IPhoneService
{
string Mobile { get; set; }
string Message { get; set; }
void Send();
}
//實現標準-不是代理模式
public class PhoneService : IPhoneService
{
public string Mobile { get; set; }
public string Message { get; set; }
public PhoneService(string mobile, string message)
{
Mobile = mobile;
Message = message;
}
public virtual void Send()
{
Console.WriteLine($"已發送簡訊:{Message}到{Mobile}");
}
}
//代理模式:
//1.實現目標對象的標準
//2.依賴目標對象(被代理對象)
//3.業務織入
public class PhoneServiceProxy : IPhoneService//實現標準
{
private readonly IPhoneService _target;
public PhoneServiceProxy1(IPhoneService target)
{
_target = target;
}
public string Mobile { get => _target.Mobile; set => _target.Mobile = value; }
public string Message { get => _target.Message; set => _target.Message = value; }
/// <summary>
/// 子類重寫父類方法
/// </summary>
public void Send()
{
Console.WriteLine("Proxy1:已對手機號進行驗證");
_target.Send();
Console.WriteLine("Proxy1:已確認對方已經收到");
}
}
/// <summary>
/// 定義標準1
/// </summary>
public interface IPhoneService
{
string Mobile { get; set; }
string Message { get; set; }
void Send();
}
/// <summary>
/// 定義標準2
/// </summary>
public interface IEmailService
{
string Email { get; set; }
string Message { get; set; }
void Send();
}
/// <summary>
/// 業務邏輯1
/// </summary>
public class PhoneService : IPhoneService
{
public string Mobile { get; set; }
public string Message { get; set; }
public PhoneService(string mobile, string message)
{
Mobile = mobile;
Message = message;
}
public virtual void Send()
{
Console.WriteLine($"已發送簡訊:{Message}到{Mobile}");
}
}
/// <summary>
/// 業務邏輯2
/// </summary>
public class EmailService : IEmailService
{
public string Email { get; set; }
public string Message { get; set; }
public EmailService(string email, string message)
{
Email = email;
Message = message;
}
public virtual void Send()
{
Console.WriteLine($"已發送郵件:{Message}到{Email}");
}
}
/// <summary>
/// 切麵1:校驗能力(系統邏輯)
/// taget方式
/// </summary>
public class PhoneServiceProxy1
: IPhoneService//實現標準1
{
private readonly IPhoneService _target;
public PhoneServiceProxy1(IPhoneService target)
{
_target = target;
}
/// <summary>
/// 子類重寫父類方法
/// </summary>
public void Send()
{
Console.WriteLine("Proxy1:已對手機號進行驗證");
_target.Send();
Console.WriteLine("Proxy1:已確認對方已經收到");
}
}
/// <summary>
/// 切麵2:加速能力(系統邏輯)
/// </summary>
public class PhoneServiceProxy2
: IPhoneService//實現標準1
{
private readonly IPhoneService _target;
public PhoneServiceProxy2(IPhoneService target)
{
_target = target;
}
/// <summary>
/// 子類重寫父類方法
/// </summary>
public void Send()
{
Console.WriteLine("Proxy2:已開啟加速通道");
_target.Send();
Console.WriteLine("Proxy2:已關閉加速通道");
}
}
//test
public static void TestStaticProxy()
{
//目標對象
IPhoneService target = new PhoneService("10088", "你好啊!");
//切麵1:驗證,對target進行代理
IPhoneService proxy1 = new PhoneServiceProxy1(target);
//切麵2:加速,對proxy1進行代理
IPhoneService proxy2 = new PhoneServiceProxy2(proxy1);
//執行
proxy2.Send();
//思考如果要實現IEmailService標準,是不是要重寫實現類了?
}
動態代理
Castle.Core
動態代理和靜態代理的區別就是,代理類由工具生成,需要在運行時確認代理類已經代理關係。代理類中的邏輯寫到攔截器裡面,可以進行復用。缺點是性能差。裡面涉及到大量反射技術。
Castle.Core:原理就是通過子類繼承父類或者實現父類標準,通過Castle.Core自動幫你生成代理類,通過一個叫攔截器的東西編寫代理類要執行的業務邏輯。Castle.Core會幫你生成代理類,並將攔截器織入到代理類中。
動態代理通過invocation進行串聯,本質是反射。
/// <summary>
/// 定義標準1
/// </summary>
public interface IPhoneService
{
string Mobile { get; set; }
string Message { get; set; }
void Send();
}
/// <summary>
/// 定義標準2
/// </summary>
public interface IEmailService
{
string Email { get; set; }
string Message { get; set; }
void Send();
}
/// <summary>
/// 業務邏輯1
/// </summary>
public class PhoneService : IPhoneService
{
public string Mobile { get; set; }
public string Message { get; set; }
public PhoneService(string mobile, string message)
{
Mobile = mobile;
Message = message;
}
public virtual void Send()
{
Console.WriteLine($"已發送簡訊:{Message}到{Mobile}");
}
}
/// <summary>
/// 業務邏輯2
/// </summary>
public class EmailService : IEmailService
{
public string Email { get; set; }
public string Message { get; set; }
public EmailService(string email, string message)
{
Email = email;
Message = message;
}
public virtual void Send()
{
Console.WriteLine($"已發送郵件:{Message}到{Email}");
}
}
/// <summary>
/// 代理1:任意標準
/// </summary>
public class ShareInterceptor1 : IInterceptor
{
public void Intercept(IInvocation invocation)
{
Console.WriteLine("Proxy1:已對接收方進行驗證");
invocation.Proceed();//執行下一個攔截器或者目標方法
Console.WriteLine("Proxy1:已確認對方已經收到");
}
}
/// <summary>
/// 代理2:任意標準
/// </summary>
public class ShareInterceptor2 : IInterceptor
{
public void Intercept(IInvocation invocation)
{
Console.WriteLine("Proxy2:已開啟加速通道");
invocation.Proceed();//執行下一個攔截器或者目標方法
Console.WriteLine("Proxy2:已關閉加速通道");
}
}
//通過Castel生成代理類
public static void TestDynamicProxy1()
{
//創建代理生成器
var generator = new ProxyGenerator();
var target1 = new PhoneService("10088", "你好啊!");
var target2 = new EmailService("[email protected]", "你好啊!");
var interceptor1 = new ShareInterceptor1();//代理1,攔截器1,不需要去實現指定的標準
var interceptor2 = new ShareInterceptor2();//代理2,攔截器2,不需要去實現指定的標準
//使用代理1和代理2去代理手機的標準
IPhoneService dynamicProxy1 = generator.CreateInterfaceProxyWithTarget<IPhoneService>(target1, interceptor1, interceptor2);
dynamicProxy1.Send();
//代理郵件的標準
IEmailService dynamicProxy2 = generator.CreateInterfaceProxyWithTarget<IEmailService>(target2, interceptor1, interceptor2);
dynamicProxy2.Send();
}
手寫Castle.Core的代理類
思考:
generator創建的是什麼類型的實列?顯然不可能是已有的類型。因為它把攔截器織入進去了。而且沒有修改我們的代碼,站在面向對象的角度來看只能是實現了我們的介面,Emit動態實現了下麵的代碼
多個攔截器和目標對象(被代理者)通過Invocation進行串聯。Invocation中的Arguments完成鏈式調用。
手動通過Invocation進行串聯
//假設有三個攔截器
//第一個攔截器invocation1:Proxy=interceptor2,Method=Intercept,argument=invocation2
//第二個攔截器invocation2:Proxy=interceptor3,Method=Intercept,argument=invocation3
//第三個攔截器invocation2:Proxy=target,Method=method,argument=arguments
//手動實現
public IInvocation GetInvocation(Stack<IInterceptor> stack, object target, Method method, objuect arguments)
{
var invocation1 = new Invocation()
{
Proxy = interceptor2,
Method = typeof(IInterceptor).GetMethod(nameof(IInterceptor.Intercept)),
Arguments = new object[]
{
new Invocation()
{
Proxy = interceptor3,
Method = typeof(IInterceptor).GetMethod(nameof(IInterceptor.Intercept)),
Arguments = new object[]
{
new Invocation()
{
Proxy = target,
Method = method,
Arguments = arguments
}
}
}
}
}
}
//遞歸實現
public IInvocation GetInvocation(Stack<IInterceptor> stack, object target, Method method, objuect arguments)
{
if(stack.Any())
{
var proxy = stack.Pop();
return new Invocation()
{
Proxy = proxy,
Method = typeof(IInterceptor).GetMethod(nameof(IInterceptor.Intercept)),
Agrumtns = GetInvocation(stack,method,argumtns)
};
}
else
{
return new Invocation()
{
Proxy = target,
Method = method,
Agrumtns = arguments
};
}
}
//Castel.Core自動幫我們生成了下麵這個類
public class CastelPhoneServiceProxy : IPhoneService
{
private IPhoneService _taget;
private IInterceptor[] _interceptors;
public CastelPhoneServiceProxy(IPhoneService taget, IInterceptor[] interceptors)
{
_taget = taget;
_interceptors = interceptors;
}
public string Mobile { get => _taget.Mobile; set => _taget.Mobile = value; }
public string Message { get => _taget.Message; set => _taget.Message = value; }
public void Send()
{
var stack = new Stack<IInterceptor>(_interceptors.Reverse());
if (stack.Any())
{
var item = stack.Pop();
var invocation = GetNextInvocation(stack);
item.Intercept(invocation);
}
else
{
_taget.Send();
}
}
/// <summary>
/// 遞歸獲取Invocaltion
/// </summary>
/// <param name="stack"></param>
/// <returns></returns>
private IInvocation GetNextInvocation(Stack<IInterceptor> stack)
{
if (stack.Any())
{
var next = stack.Pop();
return new Invocaltion
{
Arguments = new object[]
{
//遞歸
GetNextInvocation(stack)
},
Proxy = next,
Method = typeof(IInterceptor).GetMethod(nameof(IInterceptor.Intercept)) ?? throw new NullReferenceException()
};
}
else
{
return new Invocaltion
{
Arguments = new object[]
{
},
Proxy = _taget,
Method = _taget.GetType().GetMethod(nameof(IPhoneService.Send)) ?? throw new NullReferenceException()
};
}
}
}
//實現一些castle.core的介面
public class Invocaltion : IInvocation
{
public object[] Arguments { get; set; }
public Type[] GenericArguments { get; set; }
public object InvocationTarget { get; set; }
public MethodInfo Method { get; set; }
public MethodInfo MethodInvocationTarget { get; set; }
public object Proxy { get; set; }
public object ReturnValue { get; set; }
public Type TargetType { get; set; }
public IInvocationProceedInfo CaptureProceedInfo()
{
throw new NotImplementedException();
}
public object GetArgumentValue(int index)
{
throw new NotImplementedException();
}
public MethodInfo GetConcreteMethod()
{
throw new NotImplementedException();
}
public MethodInfo GetConcreteMethodInvocationTarget()
{
throw new NotImplementedException();
}
public void Proceed()
{
Method.Invoke(Proxy, Arguments);
}
public void SetArgumentValue(int index, object value)
{
throw new NotImplementedException();
}
}
EMIT實現
//鏈路器
public class EmitInvocation
{
private object? proxy;
private MethodInfo? method;
private object[]? arguments;
public EmitInvocation(object? proxy, MethodInfo? method, object[]? arguments)
{
this.proxy = proxy;
this.method = method;
this.arguments = arguments;
}
public void Proceed()
{
method?.Invoke(proxy, arguments);
}
}
//攔截器
public interface IEmitInteceptor
{
void Intercept(EmitInvocation invocation);
}
//實現攔截器1
public class EmitInteceptor1 : IEmitInteceptor
{
public void Intercept(EmitInvocation invocation)
{
Console.WriteLine("prox1:start");
invocation.Proceed();
Console.WriteLine("prox1:end");
}
}
//實現攔截器1
public class EmitInteceptor2 : IEmitInteceptor
{
public void Intercept(EmitInvocation invocation)
{
Console.WriteLine("prox2:start");
invocation.Proceed();
Console.WriteLine("prox2:end");
}
}
//該工具類幫助我們少寫emit代碼
public static class EmitProxyInvoker
{
public static EmitInvocation GetNextInvocation(Stack<IEmitInteceptor> stack, MethodInfo method, object target, object[] arguments)
{
if (stack.Any())
{
var next = stack.Pop();
arguments = new object[]
{
//遞歸
GetNextInvocation(stack, method, target, arguments)
};
return new EmitInvocation(next, typeof(IEmitInteceptor).GetMethod(nameof(IEmitInteceptor.Intercept)), arguments);
}
else
{
return new EmitInvocation(target, method, arguments);
}
}
public static void Invoke(IEmitInteceptor[] interceptors, MethodInfo method, object target, object[] arguments)
{
var stack = new Stack<IEmitInteceptor>(interceptors.Reverse());
if (stack.Any())
{
var item = stack.Pop();
var invocation = GetNextInvocation(stack, method, target, arguments);
item.Intercept(invocation);
}
else
{
method.Invoke(target, arguments);
}
}
}
//業務介面
public interface IEmitService
{
void Send();
}
//將來要生成的代理類
public class EmitServiceProxy : IEmitService
{
private object _target;
private IEmitInteceptor[] _inteceptors;
public EmitService()
{
}
public void Send()
{
var method = _target.GetType().GetMethod(nameof(EmitService.Send));
var arguments = new object[] { };
EmitProxyInvoker.Invoke(_inteceptors, method, _target, new object[] { });
}
}
public static class EmitProxyGenerator
{
static AssemblyBuilder _assemblyBuilder;
static ModuleBuilder _moduleBuilder;
static EmitProxyGenerator()
{
//創建一個程式集
var assemblyName = new AssemblyName("DynamicProxies");
_assemblyBuilder = AssemblyBuilder
.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Run);
//創建一個模塊
_moduleBuilder = _assemblyBuilder.DefineDynamicModule("Proxies");
}
public static TInterface Create<TInterface>(object target, params IEmitInteceptor[] inteceptor)
where TInterface : class
{
#region 定義類型
//定義一個class,如果這個類型已定義直接返回,緩存
var typeName = $"{target.GetType().Name}EmitProxy";
var typeBuilder = _moduleBuilder.DefineType(
typeName,
TypeAttributes.Public,typeof(object),
new Type[]
{
typeof(TInterface)
});
#endregion
#region 定義欄位
//定義欄位
var targetFieldBuilder = typeBuilder.DefineField("target", typeof(object), FieldAttributes.Private);
var inteceptorFieldBuilder = typeBuilder.DefineField("inteceptor", typeof(IEmitInteceptor[]), FieldAttributes.Private);
#endregion
#region 定義構造器
//定義構造器
var constructorBuilder = typeBuilder.DefineConstructor(MethodAttributes.Public, CallingConventions.ExplicitThis, new Type[]
{
typeof(object),
typeof(IEmitInteceptor[])
});
//獲取IL編輯器
var generator = constructorBuilder.GetILGenerator();
generator.Emit(OpCodes.Ldarg_0);//載入this
generator.Emit(OpCodes.Call, typeof(object).GetConstructor(Type.EmptyTypes) ?? throw new InvalidOperationException());
generator.Emit(OpCodes.Nop);
generator.Emit(OpCodes.Nop);
// this.age = age;
generator.Emit(OpCodes.Ldarg_0);//載入this
generator.Emit(OpCodes.Ldarg_1);//載入target參數
generator.Emit(OpCodes.Stfld, targetFieldBuilder);//載入target欄位
// this.name = name;
generator.Emit(OpCodes.Ldarg_0);//載入this
generator.Emit(OpCodes.Ldarg_2);//載入inteceptor參數
generator.Emit(OpCodes.Stfld, inteceptorFieldBuilder);//載入inteceptor欄位
generator.Emit(OpCodes.Ret);
#endregion
#region 實現介面
var methods = typeof(TInterface).GetMethods();
foreach (var item in methods)
{
var parameterTypes = item.GetParameters().Select(s => s.ParameterType).ToArray();
var methodBuilder = typeBuilder.DefineMethod(item.Name,
MethodAttributes.Public| MethodAttributes.Final |MethodAttributes.Virtual | MethodAttributes.NewSlot | MethodAttributes.HideBySig,
CallingConventions.Standard|CallingConventions.HasThis,
item.ReturnType,
parameterTypes);
var generator1 = methodBuilder.GetILGenerator();
//init
var methodInfoLocal = generator1.DeclareLocal(typeof(MethodInfo));
var argumentLocal = generator1.DeclareLocal(typeof(object[]));
generator1.Emit(OpCodes.Nop);
generator1.Emit(OpCodes.Ldarg_0);
generator1.Emit(OpCodes.Ldfld, targetFieldBuilder);
generator1.Emit(OpCodes.Callvirt, typeof(Type).GetMethod(nameof(Type.GetType),Type.EmptyTypes));
generator1.Emit(OpCodes.Ldstr, item.Name);
generator1.Emit(OpCodes.Callvirt, typeof(Type).GetMethod(nameof(Type.GetMethod), new Type[] { typeof(string) }));
generator1.Emit(OpCodes.Stloc, methodInfoLocal);
generator1.Emit(OpCodes.Ldc_I4_0);
generator1.Emit(OpCodes.Newarr, typeof(object));
generator1.Emit(OpCodes.Stloc, argumentLocal);
generator1.Emit(OpCodes.Ldarg_0);
generator1.Emit(OpCodes.Ldfld, inteceptorFieldBuilder);
generator1.Emit(OpCodes.Ldloc_0);
generator1.Emit(OpCodes.Ldarg_0);
generator1.Emit(OpCodes.Ldfld, targetFieldBuilder);
generator1.Emit(OpCodes.Ldc_I4_0);
generator1.Emit(OpCodes.Newarr, typeof(object));
generator1.Emit(OpCodes.Call, typeof(EmitProxyInvoker).GetMethod(nameof(EmitProxyUtil.Invoke)));
generator1.Emit(OpCodes.Nop);
generator1.Emit(OpCodes.Ret);
}
#endregion
//創建:這個type可以用一個線程安全的字典緩存起來,第二次需要這個代理類的時候,就不需要在生成一次emit代碼了。
var type = typeBuilder.CreateType() ?? throw new ArgumentException();
var instance = Activator.CreateInstance(type, target, inteceptor);
return (TInterface)instance;
}
}
容器支持
public class DbContext
{
}
public class AService
{
public DbContext DbContext { get; }
public AService(DbContext context)
{
DbContext = context;
}
}
public static void Test()
{
var services = new ServiceCollection();
services.AddScoped<DbContext>();
var generator = new ProxyGenerator();
//泛型-不支持動態註入
services.AddScoped(sp =>
{
//通過容器解析依賴
var target = ActivatorUtilities.CreateInstance<AService>(sp);
return generator.CreateClassProxyWithTarget(target);
});
//反射-可以掃描批量註入
services.AddScoped(typeof(AService), sp =>
{
//通過容器解析依賴
var target = ActivatorUtilities.CreateInstance(sp, typeof(AService));
return generator.CreateClassProxyWithTarget(target);
});
}
管道方式
委托方式
1.通過委托構建管道
public delegate Task RequestDelegate(HttpContext context);
public class HttpContext
{
}
public class ApplicationBuilder
{
private readonly List<Func<RequestDelegate, RequestDelegate>> _componen
public void Use(Func<RequestDelegate, RequestDelegate> middleware)
{
_components.Add(middleware);
}
public void Use(Func<HttpContext, Func<Task>, Task> middleware)
{
_components.Add((next) =>
{
return async c =>
{
await middleware(c, () => next(c));
};
});
}
public void Use(Func<HttpContext, RequestDelegate, Task> middleware)
{
_components.Add((next) =>
{
return async c =>
{
await middleware(c, next);
};
});
}
public void Run(RequestDelegate handler)
{
_components.Add((next) =>
{
return async c =>
{
await handler(c);
};
});
}
//構建管道
public RequestDelegate Build()
{
RequestDelegate app = c =>
{
throw new InvalidOperationException("無效的管道");
};
for (int i = _components.Count - 1; i > -1; i--)
{
app = _components[i](app);
}
return app;
}
}
介面方式
2.通過介面構建管道
有點類型動態代理,動態代理是通過Invocation進行反射,而下麵的方式是通過介面的方式。反射更加靈活,性能不行。
public interface IChain
{
Task NextAsync();
}
public class FilterChain : IChain
{
private readonly IFilter _filter;
private readonly HttpContext _context;
private readonly IChain _next;
public FilterChain(IFilter filter, HttpContext context, IChain next)
{
_filter = filter;
_context = context;
_next = next;
}
public async Task NextAsync()
{
await _filter.InvokeAsync(_context, _next);
}
}
public class ServletChain : IChain
{
private readonly IServlet _servlet;
private readonly HttpContext _context;
public ServletChain(IServlet servlet, HttpContext context)
{
_servlet = servlet;
_context = context;
}
public async Task NextAsync()
{
await _servlet.DoPostAsync(_context);
}
}
public interface IFilter
{
Task InvokeAsync(HttpContext context, IChain chain);
}
public class Filter1 : IFilter
{
public async Task InvokeAsync(HttpContext context, IChain chain)
{
Console.WriteLine("身份認證開始");
await chain.NextAsync();
Console.WriteLine("身份認證結束");
}
}
public class Filter2 : IFilter
{
public async Task InvokeAsync(HttpContext context, IChain chain)
{
Console.WriteLine("授權認證開始");
await chain.NextAsync();
Console.WriteLine("授權認證結束");
}
}
public interface IServlet
{
Task DoPostAsync(HttpContext context);
}
public class HelloServlet : IServlet
{
public Task DoPostAsync(HttpContext context)
{
Console.WriteLine("Hello World");
return Task.CompletedTask;
}
}
public class WebHost
{
private readonly List<IFilter> _filters = new List<IFilter>();
public void AddFilter(IFilter filter)
{
_filters.Add(filter);
}
public void Exeucte(HttpContext context, IServlet servlet)
{
//自行處理filter為空的情況,就是直接執行serlvet就好了
var stack = new Stack<IFilter>(_filters);
var filter = stack.Pop();
var chain = GetFilterChain(context, servlet,stack);
filter.InvokeAsync(context, chain);
}
private IChain GetFilterChain(HttpContext context, IServlet servlet, Stack<IFilter> filters)
{
if (filters.Any())
{
var filter = filters.Pop();
var chain = GetFilterChain(context, servlet, filters);
return new FilterChain(filter, context, chain);
}
else
{
return new ServletChain(servlet, context);
}
}
}
AOP總結
1.代理分為靜態代理和動態代理,靜態代理需要自己編寫代理類,動態代理由框架生成代理類。
2.代理和管道都需要通過介面(委托)進行鏈接,串聯,形成鏈式調用。
3.動態代理慎用,因為涉及到反射技術,而且對非同步支持不友好。
4.靜態代理常用於加強已有類型,比如介面要求一個IList,我們已經擁有了一個list實列,我們需要在在list.Add方法時列印日誌,此時我們可以不改變原有的list,通過靜態代理實現IList介面來進行對原有的list加強。這個方法在更改框架的時候很有用。我們可以對原有的HttpContext,進行加強。