AOP 是 Aspect-Oriented programming 的缩写,中文翻译为面向切面编程,它是OOP(Object-Oriented Programing,面向对象编程)的补充和完善。它和OOP一样是一种编程思想。

AOP基本概念

横切(cross-cutting):与对象核心功能无关的公共行为

关注点(concern):一块我们感兴趣的区域

方面(Aspect):就是将那些与业务无关,却为业务模块所共同调用的逻辑或责任封装起来,便于减少系统的重复代码,降低模块间的耦合度,并有利于未来的可操作性和可维护性。

连接点(join point):是程序执行中一个精确执行点,例如类中的一个方法。它是一个抽象的概念,在实现AOP时,并不需要去定义一个连接点。

切入点(point cut):本质是一个捕获连接点的结构。在AOP中,可以定义一个切入点来捕获相关方法的调用。

通知(advice):是“切入点”的执行方代码,是执行“方面”的具体逻辑

引入(introduce):为对象引入附加的方法或属性,从而达到修改对象结构的目的

AOP本质
    OOP通过封装、继承及多态等概念来建立一种对象层次结构,用来模式现实事物。因为OOP中每个对象都是独立的,因此当我们需要引入公共行为时(日志、安全、异常),代码显得比较臃肿。而AOP很好的解决了这一问题。它剖开对象内部把”横切”的代码封装成一个“方面”。引用大牛的形象比喻来说“如果说“对象”是一个空心的圆柱体,其中封装的是对象的属性和行为;那么面向方面编程的方法,就仿佛一把利刃,将这些空心圆柱体剖开,以获得其内部的消息。而剖开的切面,也就是所谓的“方面”了。然后它又以巧夺天功的妙手将这些剖开的切面复原,不留痕迹。”
    AOP把软件系统分为两个部分:核心关注点和横切关注点。业务处理的主要流程部分是核心关注点,与之关系不大的部分是横切关注点。AOP的作用在于分离系统中各种关注点,将核心关注点和横切关注点分离开来。

AOP实现方式
    实现AOP的方式有两种:一是动态代理技术,二是采用静态织入方式
    动态代理:利用截取消息的方式,对该消息进行装饰,以取代原有对象行为的执行。一般通过Emit来动态的创建代理类;
    静态织入:通过引入特定的语法来创建“方面”,从而在编译期间就织入了“方面”的代码。目前这种实现方式,都是对编译器扩展。这种实现方式性能是最好的

采用动态代理实现AOP
    在说动态代理之前,我们要看一下之前是怎么实现“横切”的。
    首先,我们有这样一个类,负责处理用户的业务逻辑。

   public interface IUserService
{
bool AddUser(User user);
IList<User> GetUsers();
} public class UserService : IUserService
{
public bool AddUser(User user)
{
Console.WriteLine("添加人员:{0}", user.Name);
return true;
} public IList<User> GetUsers()
{
return new List<User>
{
new User{Name = "张三",BirthDate = DateTime.Now.AddYears(-1)},
new User{Name = "李四",BirthDate = DateTime.Now.AddYears(-2)},
new User{Name = "王五",BirthDate = DateTime.Now.AddYears(-3)},
};
}
}

    现在我们要给所有的核心业务添加日志记录的功能,我们以下几种选择:

1、直接在方法内部添加日志记录的代码

   public class UserService : IUserService
{
public bool AddUser(User user)
{
Console.WriteLine("添加人员:{0}", user.Name);
Console.WriteLine("Log:AddUser"); return true;
} public IList<User> GetUsers()
{
Console.WriteLine("Log:GetUsers");
return new List<User>
{
new User{Name = "张三",BirthDate = DateTime.Now.AddYears(-1)},
new User{Name = "李四",BirthDate = DateTime.Now.AddYears(-2)},
new User{Name = "王五",BirthDate = DateTime.Now.AddYears(-3)},
};
}
}

2、添加一个继承UserServeice的子类,并重写/覆盖父类的方法

  public class MyUserService : UserService
{
public new bool AddUser(User user)
{
base.AddUser(user);
Console.WriteLine("Log:AddUser");
return true;
} public new IList<User> GetUsers()
{
Console.WriteLine("Log:GetUsers");
return base.GetUsers();
} }

3、写一个静态的代理类

首先声明一个拦截器接口

  public interface IInterceptor
{
object Invoke(object obj, string methodName, object[] paramters);
}

然后创建一个日志拦截器

 public class LogInterceptor : IInterceptor
{
public object Invoke(object obj, string methodName, object[] paramters)
{
Console.WriteLine("Log:{0}", methodName); object result = obj.GetType().GetMethod(methodName).Invoke(obj, paramters); return result;
}
}

最后创建静态代理类

        public class MyUserServiceProxy
{
private readonly IInterceptor _interceptor;
private readonly User _user;
public MyUserServiceProxy(User user, IInterceptor interceptor)
{
_user = user;
_interceptor = interceptor;
} public bool AddUser(User user)
{
return (bool)_interceptor.Invoke(_user, "AddUser", new object[] { user });
} public IList<User> GetUsers()
{
return (IList<User>)_interceptor.Invoke(_user, "GetUsers", null); } }

下面调用

var proxy = new AOPTest.MyUserServiceProxy(new AOPTest.User
{
Name = "Khadron",
BirthDate = DateTime.Now
},
new AOPTest.LogInterceptor()); IList<AOPTest.User> users = proxy.GetUsers(); if (users.Count > 0)
{
proxy.AddUser(users[0]);
} Console.ReadKey();

    相对于前面的两种方法,第三种方法算是比较好的了,不过还是不够好,缺点是不仅必须给每个业务类都重写一个包含日志处理的代理类,而且如果还有其他类似日志处理的模块(权限),那还需要在写一个其他代理类,这样做起来不仅工作量大,而且维护起来也十分麻烦。 采用动态代理的方式很好的解决了这个问题,上面说过主要采用Emit来实现,代码太多就不贴了,请查看我的github,这里面实现了一个简单的AOP框架

.NET平台下AOP框架

    动态代理:Castle Dynamic ProxyUnityLOOM.NET

    静态织入:Postsharp(收费)Eos

个人推荐使用 Castle框架,至此结束

AOP原理及其实现的更多相关文章

  1. spring ioc aop 原理

    spring ioc aop 原理 spring ioc aop 的原理 spring的IoC容器是spring的核心,spring AOP是spring框架的重要组成部分. 在传统的程序设计中,当调 ...

  2. SSH深度历险(十一) AOP原理及相关概念学习+xml配置实例(对比注解方式的优缺点)

    接上一篇 SSH深度历险(十) AOP原理及相关概念学习+AspectJ注解方式配置spring AOP,本篇我们主要是来学习使用配置XML实现AOP 本文采用强制的CGLB代理方式 Security ...

  3. SSH深度历险(十) AOP原理及相关概念学习+AspectJ注解方式配置spring AOP

    AOP(Aspect Oriented Programming),是面向切面编程的技术.AOP基于IoC基础,是对OOP的有益补充. AOP之所以能得到广泛应用,主要是因为它将应用系统拆分分了2个部分 ...

  4. 面试问烂的 Spring AOP 原理、SpringMVC 过程(求求你别问了)

    Spring AOP ,SpringMVC ,这两个应该是国内面试必问题,网上有很多答案,其实背背就可以.但今天笔者带大家一起深入浅出源码,看看他的原理.以期让印象更加深刻,面试的时候游刃有余. Sp ...

  5. spring MVC 及 AOP 原理

    SpringMVC工作原理https://www.cnblogs.com/xiaoxi/p/6164383.htmlspring MVC 原理https://blog.csdn.net/y199108 ...

  6. spring aop 原理学习

    @EnableAspectJAutoProxy: @Import(AspectJAutoProxyRegistrar.class) 实际是创建了一个以org.springframework.aop.c ...

  7. Spring之AOP原理、代码、使用详解(XML配置方式)

    Spring 的两大核心,一是IOC,另一个是AOP,本博客从原理.AOP代码以及AOP使用三个方向来讲AOP.先给出一张AOP相关的结构图,可以放大查看. 一.Spring AOP 接口设计 1.P ...

  8. 34、[源码]-AOP原理-链式调用通知方法

    34.[源码]-AOP原理-链式调用通知方法

  9. 33、[源码]-AOP原理-获取拦截器链-MethodInterceptor

    33.[源码]-AOP原理-获取拦截器链-MethodInterceptor

  10. 31、[源码]-AOP原理-AnnotationAwareAspectJAutoProxyCreato机

    31.[源码]-AOP原理-AnnotationAwareAspectJAutoProxyCreato机

随机推荐

  1. 3)Win10-UWA开发 API參考 - 2

     孙广东  2015.8.23 二.适用于 UWP 应用的 .NET 摘要 适用于 UWP 应用的 .NET 提供一组托管类型.你能够利用这组托管类型通过 C# 或 Visual Basic 创建 ...

  2. Java之JDBC学习

    (一),MySql数据库 1,MySql数据库的数据类型定义 2,完整性约束: 3,索引: 作用:唯一作用就是加快对表查询速度,索引通过快速路径方法访问来快速定位数据,从而减少磁盘的II/O; 缺点: ...

  3. fabricjs 高级篇(自定义类型)

    原文:https://www.sitepoint.com/fabric-js-advanced/ <html> <head> <script src='./js/fabr ...

  4. 配置 FIS 来适配 go revel 框架以优化前端缓存策略

    对于前端工程师来说,浏览器缓存优化是个永远的话题.前几天看了知乎上的一个问答:<大公司里怎样开发和部署前端代码?>,深以为然,所以决心使用 FIS 来优化自身的前端文件. 我们的项目使用了 ...

  5. [Algorithms] Refactor a Linear Search into a Binary Search with JavaScript

    Binary search is an algorithm that accepts a sorted list and returns a search element from the list. ...

  6. Intellij idea远程debug连接tomcat,实现单步调试

    转载:http://blog.csdn.net/boling_cavalry/article/details/73384036 web项目部署到tomcat上之后,有时需要打断点单步调试,如果用的是I ...

  7. c语言用rand() 函数,实现random(int m)

    函数rand()是真正的随机数生成器.而srand()会设置供rand()使用的随机数种子. 假设你在第一次调用rand()之前没有调用srand(),那么系统会为你自己主动调用srand(). 注意 ...

  8. 【Excle数据透视表】如何为一个字段添加多种分类汇总方式

    解决方案1 右键单击人员分类字段包含的任意单元格→右键→字段设置→自定义→(最大值.最小值) 解决方案2 单击人员分类→分析→字段设置

  9. 关系型数据的分布式处理系统MyCAT(转载)

      ——概述和基本使用教程 日期:2014/12/24 文:阿蜜果 1.   MyCAT概述 1.1 背景 随着传统的数据库技术日趋成熟.计算机网络技术的飞速发展和应用范围的扩充,数据库应用已经普遍建 ...

  10. checked exception和unchecked exception区别

    http://blog.csdn.net/yuefengyuan/article/details/6204317 一. Java 中定义了两类异常: 1) Checked exception: 这类异 ...