add by zhj:面向切面编程就是在不修改函数A的前提下,在函数A前后插入业务逻辑B, C, D..。这其实算是功能分解,将大模块S=A+B+C+D+……分解为独立的小功能A,B,C,D……,模块化可使得功能复用、低耦合,不过这种分解也不是粒度越细越好。

原文:http://blog.zoneke.com/blog/2012/12/25/qie-mian-bian-cheng/

什么是面向切面编程?

面向切面编程, Aspect Oriented Programming(AOP)。主要实现的是将业务逻辑处理过程以切面为维度进行提取,它所面对的是处理过程中的某个步骤或阶段,以获得逻辑过程中各部分之间低耦合性的隔离效果。也就是说,在不修改函数A的前提下,在函数A前后插入业务逻辑B, C, D..

基于Python Decorator的切面编程

Python的decorator功能很强大,它能在运行期间拿到函数的上下文,并且赋予你足够的权限去做很多事情。这恰恰符合面向切面编程的设计方式,你可以通过decorator方便的实现这个功能。

直接上代码:

func_section decorator代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
def func_section(before_chain=[], after_chain=[]):
def func_wrap(func):
def wrap(*args, **kwargs):
for before_func in before_chain:
try:
before_func(*args, **kwargs)
except Exception:
continue
res = func(*args, **kwargs)
for after_func in after_chain:
try:
after_func(*args, **kwargs)
except Exception:
continue
return res
return wrap
return func_wrap

如何使用?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
def example():
def before_saying(self):
print("I know your name %s" % self.name)
def before_saving(self):
print("I will notify your name %s" % self.name)
def after_saving(self):
print("After saving your name %s " % self.name)
def done(self):
print("Everything is ok %s " % self.name)
class FuncTest():
def __init__(self, name):
self.name = name
def __i_know_you(self):
print("I know you guy %s " % self.name)
@func_section(before_chain=[__i_know_you,
before_saying, before_saving],
after_chain=[after_saving, done])
def save(self):
print("Save name %s " % self.name)
return self.name
test = FuncTest(name=u'chenchiyuan')
print(test.save())
>>> example()
I know you guy chenchiyuan
I know your name chenchiyuan
I will notify your name chenchiyuan
Save name chenchiyuan
After saving your name chenchiyuan
Everything is ok chenchiyuan
chenchiyuan

看了这么多,它能干什么?

它的作用就是减少你的代码的耦合度

还不明白?我来举个最简单的例子。

现在有个函数叫做eat(),业务逻辑就是饿了要吃饭,而且已经很多地方调用它了。现在我有个需求,在每次吃饭之前我要吃点开胃菜before_eat(),吃饭之后,我要刷牙洗口after_eat()。怎么实现呢?

1. 懒人的方法

管它三七二十一,直接修改eat(), 先加上before_eat(), 再加上after_eat()。

评价:确实完成了功能。但是违反了开闭原则,而且函数耦合性很高,如果以后添加了更多需求,这段代码会臃肿不堪,业务逻辑复杂到一定规模的时候,你就祈祷神来解决你吧。

2. 最笨的方法

全文搜索,找出所有用到eat()的地方,前面加上before_eat(),后面加上after_eat()。

评价:违反了封装原则,这一系列操作对外应该是不可见的。我都懒得评价了。。

3. 优雅的方法

使用面向切面编程的方法。

1
2
3
4
5
6
7
8
9
def before_eat():
print(u'吃开胃菜')
def after_eat():
print(u'刷牙')
@func_section(before_chain=[before_eat, ], after_chain=[after_eat, ])
def eat():
print(u'吃饭')

这样,以后业务逻辑增加了,只需要将原子的业务逻辑加入函数执行链中即可。体验到它的强大了吧?

题外话

1. Django中有没有类似的方式?

肯定是有的,最接近的其实是signal的实现。把model.save()比喻成eat(), 那么你可以通过Django自带的before_save, after_save来实现在save的切面前后添加业务逻辑。这样做远远比你重写save方法好得多。

2. 还有什么注意的东西?

顺便提提对象的方法实现。instance.do_something(args, **kwargs)。在切面编程拿到的形式是do_something(instance, args, **kwargs)。这其实就是面向对象的最核心的实现技巧。

面向切面编程--AOP(转)的更多相关文章

  1. 设计模式之面向切面编程AOP

    动态的将代码切入到指定的方法.指定位置上的编程思想就是面向切面的编程. 代码只有两种,一种是逻辑代码.另一种是非逻辑代码.逻辑代码就是实现功能的核心代码,非逻辑代码就是处理琐碎事务的代码,比如说获取连 ...

  2. Spring学习手札(二)面向切面编程AOP

    AOP理解 Aspect Oriented Program面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术. 但是,这种说法有些片面,因为在软件工程中,AOP的价值体现的并 ...

  3. Spring学习笔记:面向切面编程AOP(Aspect Oriented Programming)

    一.面向切面编程AOP 目标:让我们可以“专心做事”,避免繁杂重复的功能编码 原理:将复杂的需求分解出不同方面,将公共功能集中解决 *****所谓面向切面编程,是一种通过预编译方式和运行期动态代理实现 ...

  4. Spring框架学习笔记(2)——面向切面编程AOP

    介绍 概念 面向切面编程AOP与面向对象编程OOP有所不同,AOP不是对OOP的替换,而是对OOP的一种补充,AOP增强了OOP. 假设我们有几个业务代码,都调用了某个方法,按照OOP的思想,我们就会 ...

  5. Spring之控制反转——IoC、面向切面编程——AOP

      控制反转——IoC 提出IoC的目的 为了解决对象之间的耦合度过高的问题,提出了IoC理论,用来实现对象之间的解耦. 什么是IoC IoC是Inversion of Control的缩写,译为控制 ...

  6. 【串线篇】面向切面编程AOP

    面向切面编程AOP 描述:将某段代码“动态”的切入到“指定方法”的“指定位置”进行运行的一种编程方式 (其底层就是Java的动态代理)spring对其做了简化书写 场景: 1).AOP加日志保存到数据 ...

  7. 04 Spring:01.Spring框架简介&&02.程序间耦合&&03.Spring的 IOC 和 DI&&08.面向切面编程 AOP&&10.Spring中事务控制

    spring共四天 第一天:spring框架的概述以及spring中基于XML的IOC配置 第二天:spring中基于注解的IOC和ioc的案例 第三天:spring中的aop和基于XML以及注解的A ...

  8. [译]如何在ASP.NET Core中实现面向切面编程(AOP)

    原文地址:ASPECT ORIENTED PROGRAMMING USING PROXIES IN ASP.NET CORE 原文作者:ZANID HAYTAM 译文地址:如何在ASP.NET Cor ...

  9. Spring框架系列(4) - 深入浅出Spring核心之面向切面编程(AOP)

    在Spring基础 - Spring简单例子引入Spring的核心中向你展示了AOP的基础含义,同时以此发散了一些AOP相关知识点; 本节将在此基础上进一步解读AOP的含义以及AOP的使用方式.@pd ...

  10. 面向切面编程AOP

    本文的主要内容(AOP): 1.AOP面向切面编程的相关概念(思想.原理.相关术语) 2.AOP编程底层实现机制(动态代理机制:JDK代理.Cglib代理) 3.Spring的传统AOP编程的案例(计 ...

随机推荐

  1. [Windows] Windows 8.x 取消触摸板切换界面

    在鼠标中选中UltraNav,找到Application Gestures - Edge Swipes,取消Enable Edge Swipes.

  2. 第十七篇:IO复用之select实现

    前言 在看过前文:初探IO复用后,想必你已对IO复用这个概念有了初步但清晰的认识. 接下来,我要在一个具体的并发客户端中实现它(基于select函数),使得一旦服务器中的客户进程被终止的时候,客户端这 ...

  3. iOS - 转场时 appear 与 disappear 的调用顺序探索

    不同的转场方式 A.B viewDidDisappear调用的流程不同 在A页面跳转到B页面的过程中 A 的 viewDidDisappear 方法和 B 的 viewDidAppear 谁先调用? ...

  4. 简单mysql类

    ---恢复内容开始--- class mysql { private $host; private $user; private $pass; private $database; private $ ...

  5. 解决neo4j @Transactional 与Spring data jpa @Transactional 冲突问题,@CreatedBy,@CreatedDate,@LastModifiedBy,@LastModifiedDate,以及解决@Version失效问题

    之前mybatis特别流行,所以前几个项目都是用@SelectProvider,@InsertProvider,@UpdateProvider,@DeleteProvider 加反射泛型封装了一些通用 ...

  6. VS 2008 头文件库文件设置

    在程序开发中,很多时候需要用到别人开发的工具包,如OpenCV和itk.一般而言,在vs2008中,很少使用源文件,大部分是使用对类进行声明的头文件和封装了类的链接库(静态lib或动态dll). 如果 ...

  7. 题目1100:最短路径(最短路径问题进阶dijkstra算法)

    题目链接:http://ac.jobdu.com/problem.php?pid=1100 详细链接:https://github.com/zpfbuaa/JobduInCPlusPlus 参考代码: ...

  8. LeetCode 17 Letter Combinations of a Phone Number (电话号码字符组合)

    题目链接 https://leetcode.com/problems/letter-combinations-of-a-phone-number/?tab=Description HashMap< ...

  9. sencha touch 2.2 为list PullRefresh插件添加refreshFn方法

    sencha touch 2.2 list PullRefresh插件没有refreshFn方法 但是我们又需要他,所以需要自行扩展 代码如下 /** * 重写下拉刷新插件,以支持refreshFn事 ...

  10. Openstack Nova network

    对于安装设置来说,Openstack就剩下网络这个地方比较复杂. 现在比较喜欢看图 整理了一下网络的资料 1:Nova 网络HA http://unchainyourbrain.com/opensta ...