一、引言:
AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。AOP是OOP的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生范型。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。
二、静态拦截方式实现AOP
静态拦截方式最为简单,只是从原理上面描述AOP的实现过程。
public class Order { public int Id { set; get; } public string Name { set; get; } public int Count { set; get; } public double Price { set; get; } public string Desc { set; get; } } public interface IOrderProcessor { void Submit(Order order); } public class OrderProcessor : IOrderProcessor { public void Submit(Order order) { Console.WriteLine("提交订单"); } } public class OrderProcessorDecorator : IOrderProcessor { public IOrderProcessor OrderProcessor { get; set; } public OrderProcessorDecorator(IOrderProcessor orderprocessor) { OrderProcessor = orderprocessor; } public void Submit(Order order) { PreProceed(order); OrderProcessor.Submit(order); PostProceed(order); } public void PreProceed(Order order) { Console.WriteLine("提交订单前,进行订单数据校验...."); if (order.Price < 0) { Console.WriteLine("订单总价有误,请重新核对订单。"); } } public void PostProceed(Order order) { Console.WriteLine("提交带单后,进行订单日志记录......"); Console.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + "提交订单,订单名称:" + order.Name + ",订单价格:" + order.Price); } }
调用方式:
Order order = new Order() { Id = 1, Name = "lee", Count = 10, Price = 100.00, Desc = "订单测试" }; IOrderProcessor orderprocessor = new OrderProcessorDecorator(new OrderProcessor()); orderprocessor.Submit(order);
三、动态代理实现AOP
using Microsoft.Practices.Unity.InterceptionExtension; using Microsoft.Practices.Unity; using Microsoft.Practices.EnterpriseLibrary.PolicyInjection; namespace ConsoleDmeo.AOP { public class User { public string Name { set; get; } public string PassWord { set; get; } } #region 1、定义特性方便使用 public class LogHandlerAttribute : HandlerAttribute { public string LogInfo { set; get; } public int Order { get; set; } public override ICallHandler CreateHandler(IUnityContainer container) { return new LogHandler() { Order = this.Order, LogInfo = this.LogInfo }; } } #endregion #region 2、注册对需要的Handler拦截请求 public class LogHandler : ICallHandler { public int Order { get; set; } public string LogInfo { set; get; } //这个方法就是拦截的方法,可以规定在执行方法之前和之后的拦截 public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext) { Console.WriteLine("LogInfo内容" + LogInfo); //0.解析参数 var arrInputs = input.Inputs; if (arrInputs.Count > 0) { var oUserTest1 = arrInputs[0] as User; } //1.执行方法之前的拦截 Console.WriteLine("方法执行前拦截到了"); //2.执行方法 var messagereturn = getNext()(input, getNext); //3.执行方法之后的拦截 Console.WriteLine("方法执行后拦截到了"); return messagereturn; } } #endregion #region 3、用户定义接口和实现 public interface IUserOperation { void Test(User oUser); void Test2(User oUser, User oUser2); } //这里必须要继承这个类MarshalByRefObject,否则报错 public class UserOperation : MarshalByRefObject, IUserOperation { private static UserOperation oUserOpertion = null; public UserOperation() { //oUserOpertion = PolicyInjection.Create<UserOperation>(); } //定义单例模式将PolicyInjection.Create<UserOperation>()产生的这个对象传出去,这样就避免了在调用处写这些东西 public static UserOperation GetInstance() { if (oUserOpertion == null) oUserOpertion = PolicyInjection.Create<UserOperation>(); return oUserOpertion; } //调用属性也会拦截 public string Name { set; get; } //[LogHandler],在方法上面加这个特性,只对此方法拦截 [LogHandler(LogInfo = "Test的日志为aaaaa")] public void Test(User oUser) { Console.WriteLine("Test方法执行了"); } [LogHandler(LogInfo = "Test2的日志为bbbbb")] public void Test2(User oUser, User oUser2) { Console.WriteLine("Test2方法执行了"); } } #endregion }
调用方式:
var oUserTest1 = new ConsoleDmeo.AOP.User() { Name = "test2222", PassWord = "yxj" }; var oUserTest2 = new ConsoleDmeo.AOP.User() { Name = "test3333", PassWord = "yxj" }; var oUser = UserOperation.GetInstance(); oUser.Test(oUserTest1); oUser.Test2(oUserTest1, oUserTest2);
四、MVC中的filter实现AOP
自定义授权类:
public class MyAuthorizeAttribute:AuthorizeAttribute { public override void OnAuthorization(AuthorizationContext filterContext) { filterContext.Result = new RedirectResult("/Login/Index"); base.OnAuthorization(filterContext); } protected override bool AuthorizeCore(HttpContextBase httpContext) { string userName = httpContext.User.Identity.Name; if (userName == "admin") { return true; } else { return false; } } }
上面自定义了请求授权方法和自定义授权检查,在局部控制器中使用:
[MyAuthorize] public ActionResult Index() { return View(); }