一、传统的面向对象编程OOP
万物皆对象,专注于类与类之间的交互,由类组成各种功能,功能组咸亨组件,组件又组成系统,适合做大型项目。
但是,由于类是静态的,封闭的,任何需求的变化都会对其带来影响,而在项目的开发过程中,良好的设计是尽量避免对已有类型的更改,因此再前辈的经验中,总结了GOF23种设计模式, 虽然设计模式原则可以解决类与类之间的交互稳定,但如果类的自身变化,需要增加功能需求,则设计模式也解决不了,因此也就出现了面向切面编程的思想了。
二、面向切面编程AOP
面向切面编程,实际上是对OOP的一种补充
允许通过外部方式来修改对象,可以在不破坏类型封装的前提下,去提供新的功能;
AOP只是增加通用逻辑,而不实现核心业务,核心业务还是放在业务类上实现,比如事务、日志、异常、权限、校验、缓存等等。
三、AOP的实现方式:
1. 静态AOP
- 使用装饰器模式
public interface IUserService
{
void Register(User user);
}
public class UserService : IUserService
{
public void Register(User user)
{
Console.WriteLine("用户已注册。Name:{0},PassWord:{1}", user.Name, user.Password);
}
}
/// <summary>
/// 使用装饰器模式提供一个AOP功能
/// </summary>
public class UserServiceDecorator : IUserService
{
private IUserService UserService { get; set; }
public UserServiceDecorator(IUserService userService)
{
UserService = userService;
}
public void Register(User user)
{
BeforeProceed(user);
this.UserProcessor.RegUser(user);
AfterProceed(user);
}
/// <summary>
/// 业务逻辑之前
/// </summary>
/// <param name="user"></param>
public void BeforeProceed(User user)
{
Console.WriteLine("方法执行前");
}
/// <summary>
/// 业务逻辑之后
/// </summary>
/// <param name="user"></param>
public void AfterProceed(User user)
{
Console.WriteLine("方法执行后");
}
}
- 使用简单代理模式
public abstract class UserService
{
public abstract void Register(User user);
}
public class WebUserService : UserService
{
public override void Register(User user)
{
Console.WriteLine("用户已注册!");
}
}
/// <summary>
/// 使用代理模式实现AOP
/// </summary>
public class UserProxy : UserService
{
private WebUserService webUserService;
public override void Register(User user)
{
if(webUserService == null)
{
webUserService = new WebUserService();
}
webUserService.Register(user);
}
public void Before()
{
}
public void After()
{
}
}
2. 动态代理实现AOP (RealProxy/emit生成/Unity)
- 使用 .Net Remoting/RealProxy实现动态代理,此方式局限在于业务类必须是继承自MarshalByRefObject类型的类
using System.Runtime.Remoting.Messaging;
using System.Runtime.Remoting.Proxies;
public class ProxyAOP
{
public static void Show()
{
User user = new User() {
Name = "Lucas",
Password = "123456"
};
UserService UserService = TransparentProxy.Create<UserService>();
UserService.RegUser(user);
int result = UserService.GetUserId();
}
/// <summary>
/// 真实代理
/// </summary>
/// <typeparam name="T"></typeparam>
public class MyRealProxy<T> : RealProxy
{
private T tTarget;
public MyRealProxy(T target)
: base(typeof(T))
{
this.tTarget = target;
}
public override IMessage Invoke(IMessage msg)
{
BeforeProceede(msg);
IMethodCallMessage callMessage = (IMethodCallMessage)msg;
object returnValue = callMessage.MethodBase.Invoke(this.tTarget, 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("方法执行后可以加入的逻辑");
}
}
/// <summary>
/// 透明代理
/// </summary>
public static class TransparentProxy
{
public static T Create<T>()
{
T instance = Activator.CreateInstance<T>();
MyRealProxy<T> realProxy = new MyRealProxy<T>(instance);
T transparentProxy = (T)realProxy.GetTransparentProxy();
return transparentProxy;
}
}
public interface IUserService
{
void RegUser(User user);
int GetUserId();
}
/// <summary>
/// 必须继承自MarshalByRefObject父类
/// </summary>
public class UserService : MarshalByRefObject, IUserService
{
public void RegUser(User user)
{
Console.WriteLine("用户已注册。用户名称{0} Password{1}", user.Name, user.Password);
}
public int GetUserId()
{
return 123;
}
}
}
- 使用Castle\DynamicProxy 实现动态代理,其局限性为业务类的方法必须为虚方法
using Castle.DynamicProxy;
public class CastleProxyAOP
{
public static void Show()
{
User user = new User()
{
Name = "Lucas",
Password = "123456"
};
ProxyGenerator generator = new ProxyGenerator();
MyInterceptor interceptor = new MyInterceptor();
UserService UserService = generator.CreateClassProxy<UserService>(interceptor);
UserService.RegUser(user);
}
public interface IUserService
{
void RegUser(User user);
}
public class UserService : IUserService
{
/// <summary>
/// 必须带上virtual
/// </summary>
/// <param name="user"></param>
public virtual void RegUser(User user)
{
Console.WriteLine($"用户已注册。Name:{user.Name},PassWord:{user.Password}");
}
}
/// <summary>
/// 添加的通用逻辑在此类中实现,继承IItercepter类
/// </summary>
public class MyInterceptor : 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("方法执行后");
}
}
}
- 使用Unity实现动态代理,针对整个类而言,不具体到某个方法,如果想要单独为某个方法增加,在handler中检测如果是其他方法的话则直接返回就行了,当然也有其他的方式,可以使用一下的几个方式实现针对某个方法的。
TransparentProxyInterceptor:直接在类的方法上进行标记,但是这个类必须继承MarshalByRefObject…不建议用
VirtualMethod:直接在类的方法上进行标记,但这个方法必须是虚方法(就是方法要带virtual关键字)
InterfaceInterceptor:在接口的方法上进行标记,这样继承这个接口的类里实现这个接口方法的方法就能被拦截
using Unity;
using Unity.Interception.ContainerIntegration;
using Unity.Interception.Interceptors.InstanceInterceptors.InterfaceInterception;
using Unity.Interception.PolicyInjection.Pipeline;
using Unity.Interception.PolicyInjection.Policies;
public class UnityAOP
{
public static void Show()
{
User user = new User() {
Name = "Lucas",
Password = "123456"
};
IUnityContainer container = new UnityContainer();//声明一个容器
container.RegisterType<IUserService, UserService>();//声明UnityContainer并注册IUserService
IUserService processor = container.Resolve<IUserService>();
processor.RegUser(user);//调用
container.AddNewExtension<Interception>().Configure<Interception>()
.SetInterceptorFor<IUserService>(new InterfaceInterceptor());
IUserService UserService = container.Resolve<IUserService>();
UserService.RegUser(user);//调用
UserService.GetUser(user);//调用
}
#region 特性对应的行为
public class UserHandler : ICallHandler
{
public int Order { get; set; }
public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext)
{
User user = input.Inputs[0] as User;
if (user.Password.Length < 10)
{
return input.CreateExceptionMethodReturn(new Exception("密码长度不能小于10位"));
}
IMethodReturn methodReturn = getNext()(input, getNext); //等价于getNext.Invoke().Invoke(input, getNext);
return methodReturn;
}
}
public class LogHandler : ICallHandler
{
public int Order { get; set; }
/// <summary>
///
/// </summary>
/// <param name="input">方法调用的参数列表</param>
/// <param name="getNext"></param>
/// <returns></returns>
public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext)
{
User user = input.Inputs[0] as User;
string message = $"RegUser:Username:{user.Name},Password:{user.Password}";
Console.WriteLine("日志已记录,Message:{0},Ctime:{1}", message, DateTime.Now);
return getNext()(input, getNext);
}
}
public class ExceptionHandler : ICallHandler
{
public int Order { get; set; }
public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext)
{
IMethodReturn methodReturn = getNext()(input, getNext);
if (methodReturn.Exception == null)
{
Console.WriteLine("无异常");
}
else
{
Console.WriteLine($"异常:{methodReturn.Exception.Message}");
}
return methodReturn;
}
}
public class AfterLogHandler : ICallHandler
{
public int Order { get; set; }
public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext)
{
IMethodReturn methodReturn = getNext()(input, getNext);
User user = input.Inputs[0] as User;
string message = string.Format("RegUser:Username:{0},Password:{1}", user.Name, user.Password);
Console.WriteLine("完成日志,Message:{0},Ctime:{1},计算结果{2}", message, DateTime.Now, methodReturn.ReturnValue);
return methodReturn;
}
}
#endregion 特性对应的行为
#region 特性
public class UserHandlerAttribute : HandlerAttribute
{
public override ICallHandler CreateHandler(IUnityContainer container)
{
ICallHandler handler = new UserHandler() { Order = this.Order };
return handler;
}
}
public class LogHandlerAttribute : HandlerAttribute
{
public override ICallHandler CreateHandler(IUnityContainer container)
{
return new LogHandler() { Order = this.Order };
}
}
public class ExceptionHandlerAttribute : HandlerAttribute
{
public override ICallHandler CreateHandler(IUnityContainer container)
{
return new ExceptionHandler() { Order = this.Order };
}
}
public class AfterLogHandlerAttribute : HandlerAttribute
{
public override ICallHandler CreateHandler(IUnityContainer container)
{
return new AfterLogHandler() { Order = this.Order };
}
}
#endregion 特性
#region 业务
[UserHandlerAttribute(Order = 1)]
[ExceptionHandlerAttribute(Order = 3)]
[LogHandlerAttribute(Order = 2)]
[AfterLogHandlerAttribute(Order = 5)]
public interface IUserService
{
void RegUser(User user);
User GetUser(User user);
}
public class UserService : IUserService
{
public void RegUser(User user)
{
Console.WriteLine("用户已注册。");
//throw new Exception("11");
}
public User GetUser(User user)
{
return user;
}
}
#endregion 业务