1. AOP
AOP:允许开发者动态的修改静态的OO模型,就像现实生活中对象在生命周期中会不断的改变自身。
AOP是一种编程思想,是OOP思想的补充
1.1 AOP面向切面编程
1.1.1 AOP有以下好处
1.1.1.1 聚焦核心业务逻辑
权限/异常/日志/缓存/事务等通用功能可以通过AOP方式添加,程序设计简单,
1.1.1.2 功能动态扩展
集中管理,代码复用;规范化;
1.1.2 实现AOP的多种方式
l 静态实现--装饰器/代理模式
l 动态实现--Remoting/Castle(Emit)
l 静态织入--PostSharp(收费)--扩展编译工具,生成的加入额外代码
l 依赖注入容器的AOP扩展(开发)
l MVC的Filter--特性标记,然后该方法执行前/后就多了逻辑
invoker调用中心--负责反射调用方法--检查特性--有则执行额外逻辑
1.2 静态AOP实现
静态AOP 可以通过装饰器模式或代理模式进行编码实现。
1.2.1 装饰器模式实现
/// <summary>
/// 装饰器模式实现静态代理
/// </summary>
public class DecoratorAOP
{
public static void Show()
{
User user = new User()
{
Name = "Olive",
Password = "116"
};
IUserProcessor processor = new UserProcessor();
processor.RegUser(user);
Console.WriteLine("***********************");
processor = new UserProcessorDecorator(processor);
processor.RegUser(user);
}
public interface IUserProcessor
{
void RegUser(User user);
}
public class UserProcessor : IUserProcessor
{
public void RegUser(User user)
{
Console.WriteLine($"用户已注册,Name:{user.Name},Password:{user.Password}");
}
}
/// <summary>
/// 装饰器的模式去提供一个AOP功能
/// </summary>
public class UserProcessorDecorator : IUserProcessor
{
private IUserProcessor _UserProcessor { get; set; }
public UserProcessorDecorator(IUserProcessor userProcessor)
{
this._UserProcessor = userProcessor;
}
public void RegUser(User user)
{
BeforeProceed(user);
this._UserProcessor.RegUser(user);
AfterProceed(user);
}
private void BeforeProceed(User user)
{
Console.WriteLine("方法执行前");
}
private void AfterProceed(User user)
{
Console.WriteLine("方法执行后");
}
}
}
1.2.2 代理模式实现
/// <summary>
/// 代理模式实现静态代理
/// AOP在方法前后增加自定义的方法
/// </summary>
public class ProxyAOP
{
public static void Show()
{
User user = new User()
{
Name = "XF",
Password = "1165"
};
IUserProcessor processor = new UserProcessor();
processor.RegUser(user);
Console.WriteLine("****************************");
processor = new ProxyUserProcessor();
processor.RegUser(user);
}
public interface IUserProcessor
{
void RegUser(User user);
}
public class UserProcessor : IUserProcessor
{
public void RegUser(User user)
{
Console.WriteLine($"用户已注册,Name:{user.Name},Password:{user.Password}");
}
}
/// <summary>
/// 代理模式去提供一个AOP功能
/// </summary>
public class ProxyUserProcessor : IUserProcessor
{
private IUserProcessor _UserProcessor = new UserProcessor();
public void RegUser(User user)
{
BeforeProceed(user);
this._UserProcessor.RegUser(user);
AfterProceed(user);
}
private void BeforeProceed(User user)
{
Console.WriteLine("方法执行前");
}
private void AfterProceed(User user)
{
Console.WriteLine("方法执行后");
}
}
}
1.3 动态代理AOP实现
动态AOP可以通过Remoting/Castle(Emit)是实现。
1.3.1 Remoting实现
/// 使用.Net Remoting/RealProxy 实现动态代理
/// 局限在业务类必须是继承自MarshalByRefObject类型
public class RealProxyAOP
{
public static void Show()
{
User user = new User()
{
Name = "XF",
Password = "116"
};
UserProcessor processor = new UserProcessor();
processor.RegUser(user);
Console.WriteLine("************************");
UserProcessor userProcessor = TransparentProxy.Create<UserProcessor>();
userProcessor.RegUser(user);
}
public interface IUserProcessor
{
void RegUser(User user);
}
public class XFRealProxy<T> : RealProxy
{
private T t;
public XFRealProxy(T target) : base(typeof(T))
{
this.t = target;
}
public override IMessage Invoke(IMessage msg)
{
BeforeProceede(msg);
IMethodCallMessage callMessage = (IMethodCallMessage)msg;
object returnValue = callMessage.MethodBase.Invoke(this.t, callMessage.Args);
AfterProceede(msg);
return new ReturnMessage(returnValue, new object[0], 0, null, callMessage);
}
public void BeforeProceede(IMessage msg)
{
Console.WriteLine("方法执行前可以加入逻辑");
}
public void AfterProceede(IMessage msg)
{
Console.WriteLine("方法执行后加入逻辑");
}
}
public static class TransparentProxy
{
public static T Create<T>()
{
T instance = Activator.CreateInstance<T>();
XFRealProxy<T> realProxy = new XFRealProxy<T>(instance);
T transparentProxy = (T)realProxy.GetTransparentProxy();
return transparentProxy;
}
}
/// <summary>
/// 继承MarshalByRefObject父类,在支持远程处理的应用程序中,允许跨应用程序域边界访问对象。
/// </summary>
public class UserProcessor : MarshalByRefObject, IUserProcessor
{
public void RegUser(User user)
{
Console.WriteLine($"用户已注册,用户名称{user.Name},密码:{user.Password}");
}
}
}
1.3.2 Castle实现
/// <summary>
/// 使用CastleDynamicProxy实现动态代理
/// 方法是虚方法
/// </summary>
public class CastleProxyAOP
{
public static void Show()
{
User user = new User()
{
Name = "XF",
Password = "12345"
};
ProxyGenerator generator = new ProxyGenerator();
XFInterceptor interceptor = new XFInterceptor();
UserProcessor userProcessor = generator.CreateClassProxy<UserProcessor>(interceptor);
userProcessor.RegUser(user);
}
public interface IUserProcessor
{
void RegUser(User user);
}
public class UserProcessor : IUserProcessor
{
public virtual void RegUser(User user)
{
Console.WriteLine($"用户注册,Name {user.Name},Password {user.Password}");
}
}
public class XFInterceptor:IInterceptor
{
public void Intercept(IInvocation invocation)
{
PreProceed(invocation);
invocation.Proceed();//调用原始业务方法
PostProceed(invocation);
}
public void PreProceed(IInvocation invocation)
{
Console.WriteLine("方法执行前");
}
public void PostProceed(IInvocation invocation)
{
Console.WriteLine("方法执行后");
}
}
}
1.4 Unity、MVC中的AOP
1.4.1 Unitiy实现AOP
需要先在NuGet中引用如下组件:
Unity、Unity.Interception、Unity.Configuration
Unity.Interception.Configuration
1.4.1.1 IUserProcessor
定义接口
public interface IUserProcessor
{
void RegUser(User user);
User GetUser(User user);
}
1.4.1.2 UserProcessor
接口的实现类
public class UserProcessor:IUserProcessor
{
public void RegUser(User user)
{
Console.WriteLine("用户注册");
}
public User GetUser(User user)
{
return user;
}
}
1.4.1.3 MonitorBehavior
AOP添加的性能检测方法
public class MonitorBehavior: Unity.Interception.InterceptionBehaviors.IInterceptionBehavior
{
public bool WillExecute
{
get { return true; }
}
public IEnumerable<Type> GetRequiredInterfaces()
{
return Type.EmptyTypes;
}
public IMethodReturn Invoke(IMethodInvocation input, GetNextInterceptionBehaviorDelegate getNext)
{
Console.WriteLine(this.GetType().Name);
string methodName = input.MethodBase.Name;
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
var methodReturn = getNext().Invoke(input, getNext);
stopwatch.Stop();
Console.WriteLine($"{this.GetType().Name}统计方法{methodName}执行耗时{stopwatch.ElapsedMilliseconds}ms");
return methodReturn;
}
}
1.4.1.4 LogBeforeBehavior
AOP添加的日志记录方法
public class LogBeforeBehavior : Unity.Interception.InterceptionBehaviors.IInterceptionBehavior
{
public bool WillExecute
{
get { return true; }
}
public IEnumerable<Type> GetRequiredInterfaces()
{
return Type.EmptyTypes;
}
public IMethodReturn Invoke(IMethodInvocation input, GetNextInterceptionBehaviorDelegate getNext)
{
Console.WriteLine("LogBeforeBehavior");
foreach(var item in input.Inputs)
{
Console.WriteLine(item.ToString());
}
return getNext().Invoke(input, getNext);
}
1.4.1.5 ParameterCheckBehavior
AOP添加的参数检查方法
public class ParameterCheckBehavior : Unity.Interception.InterceptionBehaviors.IInterceptionBehavior
{
public bool WillExecute { get { return true; } }
public IEnumerable<Type> GetRequiredInterfaces()
{
return Type.EmptyTypes;
}
public IMethodReturn Invoke(IMethodInvocation input, GetNextInterceptionBehaviorDelegate getNext)
{
Console.WriteLine("ParameterCheckBehavior");
User user = input.Inputs[0] as User;
if (user.Password.Length < 3)
return input.CreateExceptionMethodReturn(new Exception("密码长度不能小于3位"));
else
{
Console.WriteLine("参数检测无误");
return getNext().Invoke(input, getNext);
}
}
}
1.4.1.6 CachingBehavior
AOP添加的缓存方法
public class CachingBehavior : Unity.Interception.InterceptionBehaviors.IInterceptionBehavior
{
public bool WillExecute
{
get { return true; }
}
public IEnumerable<Type> GetRequiredInterfaces()
{
return Type.EmptyTypes;
}
public IMethodReturn Invoke(IMethodInvocation input, GetNextInterceptionBehaviorDelegate getNext)
{
Console.WriteLine("CachingBehavior");
if (input.MethodBase.Name.Equals("GetUser"))
return input.CreateMethodReturn(new User() { Id = 116, Name = "XF" });
return getNext().Invoke(input, getNext);
}
}
1.4.1.7 ExceptionLoggingBehavior
AOP添加的异常记录方法
public class ExceptionLoggingBehavior : Unity.Interception.InterceptionBehaviors.IInterceptionBehavior
{
public bool WillExecute
{
get { return true; }
}
public IEnumerable<Type> GetRequiredInterfaces()
{
return Type.EmptyTypes;
}
public IMethodReturn Invoke(IMethodInvocation input, GetNextInterceptionBehaviorDelegate getNext)
{
Console.WriteLine("ExceptionLoggingBehavior");
IMethodReturn methodReturn = getNext().Invoke(input, getNext);
if (methodReturn.Exception == null)
Console.WriteLine("无异常");
else
Console.WriteLine($"异常:{methodReturn.Exception.Message}");
return methodReturn;
}
}
1.4.1.8 LogAfterBehavior
AOP添加的日志记录方法
public class LogAfterBehavior : Unity.Interception.InterceptionBehaviors.IInterceptionBehavior
{
public bool WillExecute
{
get { return true; }
}
public IEnumerable<Type> GetRequiredInterfaces()
{
return Type.EmptyTypes;
}
public IMethodReturn Invoke(IMethodInvocation input, GetNextInterceptionBehaviorDelegate getNext)
{
Console.WriteLine("LogAfterBehavior");
foreach(var item in input.Inputs)
{
Console.WriteLine(item.ToString());
}
IMethodReturn methodReturn = getNext().Invoke(input, getNext);
Console.WriteLine("LogAfterBehavior" + methodReturn.ReturnValue);
return methodReturn;
}
}
1.4.1.9 UnityConfigAOP
public class UnityConfigAOP
{
public static void Show()
{
User user = new User()
{
Name = "XF",
Password = "116"
};
#region配置UnityContainer(通用代码)
IUnityContainer container = new UnityContainer();
ExeConfigurationFileMap fileMap = new ExeConfigurationFileMap();
fileMap.ExeConfigFilename = Path.Combine(AppDomain.CurrentDomain.BaseDirectory + "CfgFiles\Unity.Config");
Configuration configuration = ConfigurationManager.OpenMappedExeConfiguration(fileMap, ConfigurationUserLevel.None);
UnityConfigurationSection configurationSection = (UnityConfigurationSection)configuration.GetSection(UnityConfigurationSection.SectionName);
configurationSection.Configure(container, "AOPContainer");
#endregion
IUserProcessor processor = container.Resolve<IUserProcessor>();
processor.RegUser(user);
processor.GetUser(user);
}
}