面向切面编程AOP——加锁、cache、logging、trace、同步等这些较通用的操作,如果都写一个类,则每个用到这些功能的类使用多继承非常难看,AOP就是解决这个问题的,python AOP就是装饰器
面向切面编程(AOP)是一种编程思想,与OOP并不矛盾,只是它们的关注点相同。面向对象的目的在于抽象和管理,而面向切面的目的在于解耦和复用。
举两个大家都接触过的AOP的例子:
1)java中mybatis的@Transactional注解,大家知道被这个注解注释的函数立即就能获得DB的事务能力。
2)python中的with threading.Lock(),大家知道,被这个with代码块包裹的部分立即获得同步的锁机制。
这样我们把事务和加锁这两种与业务无关的逻辑抽象出来,在逻辑上解耦,并且可以轻松的做到代码复用。
二、上下文管理器contextlib
当然你可以使用with上下文管理器实现一些AOP的思想,这里有个模块叫contextlib可以帮助你简易的实现上下文管理器。
上下文管理最常见的例子是with open('file') as fh,回收打开句柄的例子。
这种方式还是比较麻烦的,下面我们看一下python中的装饰器怎么样实现AOP编程。
三、装饰器:AOP的语法糖
python中的装饰器就是设计来实现切面注入功能的。下面给出几个例子,这几个例子都是在生产环境验证过的。
其中的任务管理机是伪代码,需要自己实现写数据库的逻辑。
1、重试逻辑
只要do函数被@retry_exp装饰,便可以获得指数退避的重试能力。
@retry_exp(max_retries=10)
def do():
# do whatever
pass
那retry_exp是如何实现的呢?
def retry_exp(max_retries=3, max_wait_interval=10, period=1, rand=False): def _retry(func): def __retry(*args, **kwargs):
MAX_RETRIES = max_retries
MAX_WAIT_INTERVAL = max_wait_interval
PERIOD = period
RAND = rand retries = 0
error = None
ok = False
while retries < MAX_RETRIES:
try:
ret = func(*args, **kwargs)
ok = True
return ret
except Exception, ex:
error = ex
finally:
if not ok:
sleep_time = min(2 ** retries * PERIOD if not RAND else randint(0, 2 ** retries) * PERIOD, MAX_WAIT_INTERVAL)
time.sleep(sleep_time)
retries += 1
if retries == MAX_RETRIES:
if error:
raise error
else:
raise Exception("unknown")
return __retry
return _retry
2、降级开关
只要do函数被@degrade装饰,就会安装app名称校验redis里的开关,一旦发现开关关闭,则do函数不被执行,也就是降级。
@degrade
def do(app):
# do whatever
pass
那么degrade是怎样实现的呢?
def degrade(app): def _wrapper(function): def __wrapper(*args, **kwargs): value = None
try:
redis = codis_pool.get_connection()
value = redis.get("dmonitor:degrade:%s" % app)
except Exception, _:
logger.info(traceback.format_exc()) if not value or int(value) != 1:
function()
logger.info("[degrade] is_on: %s" % app)
else:
logger.info("[degrade] is_off: %s" % app)
return __wrapper return _wrapper
3、任务状态机
这个是最常用的,我们需要跟踪落盘DB一个任务的执行状态(等待调度,执行中,执行成功,执行失败)
一旦do方法被@tasks_decorator装饰,就获得了这样的能力。对item_param(是个json)中task_id指明的任务进行状态管理。
@tasks_decorator
def do(item_param):
# do whatever
pass
tasks_decorator是怎样实现的呢?
def tasks_decorator(function):
def _wrap(*args, **kwargs):
param_dict = kwargs.get('item_param')
task_id = param_dict.get('task_id')
try:
param_dict.update({'status': TaskStatus.Waiting, 'start_time': datetime.now().strftime('%Y-%m-%d %H:%M:%S')})
try:
manager_dao.save_task(param_dict)
except Exception, ex:
pass
_update_task_status(task_id, TaskStatus.Doing)
function(*args, **kwargs)
_update_task_status(task_id, TaskStatus.Done)
except Exception as e:
time.sleep(0.5)
_update_task_status(task_id, TaskStatus.Fail, unicode(e.message))
raise
return _wrap
4、全局唯一性
在分布式+异步环境中,如果想保证exactly once是需要额外的逻辑的,其实主要是实现唯一键,一旦唯一键实现了,就可以使用公共缓存redis进行唯一键判定了。
do函数被unique装饰,那么对于task_id对应的任务,全局只会执行一次。
@unique
def do(task_id):
# do whatever
pass
unique是怎样实现的呢?
def unique(function):
def _wrap(*args, **kwargs):
task_id = kwargs.get('task_id')
try:
redis = codis_pool.get_connection()
key = "unique:%s" % task_id
if not redis.setnx(key):
redis.expire(key, 24*60*60)
function(*args, **kwargs)
except Exception as e:
logger.error(traceback.format_exc())
raise
return _wrap
四、总结
AOP在少量增加代码复杂度的前提下,显著的获得以下优点:
1、使得功能逻辑和业务逻辑解耦,功能和业务的修改完全独立,代码结构清晰,开发方便
2、一键注入,代码复用程度高,扩展方便
应用举例
1
2
3
4
5
|
abstract class Worker { abstract void locked(); abstract void accessDataObject(); abstract void unlocked(); } |

应用范围
实现项目
作用
面向切面编程AOP——加锁、cache、logging、trace、同步等这些较通用的操作,如果都写一个类,则每个用到这些功能的类使用多继承非常难看,AOP就是解决这个问题的,python AOP就是装饰器的更多相关文章
- Method Swizzling和AOP(面向切面编程)实践
Method Swizzling和AOP(面向切面编程)实践 参考: http://www.cocoachina.com/ios/20150120/10959.html 上一篇介绍了 Objectiv ...
- 依赖注入(DI)有助于应用对象之间的解耦,而面向切面编程(AOP)有助于横切关注点与所影响的对象之间的解耦(转good)
依赖注入(DI)有助于应用对象之间的解耦,而面向切面编程(AOP)有助于横切关注点与所影响的对象之间的解耦.所谓横切关注点,即影响应用多处的功能,这些功能各个应用模块都需要,但又不是其主要关注点,常见 ...
- 杂项-编程:AOP(面向切面编程)
ylbtech-杂项-编程:AOP(面向切面编程) 在软件业,AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一 ...
- 面向切面编程AOP
本文的主要内容(AOP): 1.AOP面向切面编程的相关概念(思想.原理.相关术语) 2.AOP编程底层实现机制(动态代理机制:JDK代理.Cglib代理) 3.Spring的传统AOP编程的案例(计 ...
- Python装饰器与面向切面编程
今天来讨论一下装饰器.装饰器是一个很著名的设计模式,经常被用于有切面需求的场景,较为经典的有插入日志.性能测试.事务处理等.装饰器是解决这类问题的绝佳设计,有了装饰器,我们就可以抽离出大量函数中与函数 ...
- 【转】Python装饰器与面向切面编程
原文请参考: http://www.cnblogs.com/huxi/archive/2011/03/01/1967600.html 今天来讨论一下装饰器.装饰器是一个很著名的设计模式,经常被用于有切 ...
- 从壹开始前后端分离【 .NET Core2.0 +Vue2.0 】框架之十 || AOP面向切面编程浅解析:简单日志记录 + 服务切面缓存
代码已上传Github+Gitee,文末有地址 上回<从壹开始前后端分离[ .NET Core2.0 Api + Vue 2.0 + AOP + 分布式]框架之九 || 依赖注入IoC学习 + ...
- 面向切面编程--AOP(转)
add by zhj:面向切面编程就是在不修改函数A的前提下,在函数A前后插入业务逻辑B, C, D...这其实算是功能分解,将大模块S=A+B+C+D+……分解为独立的小功能A,B,C,D……,模块 ...
- Python装饰器与面向切面编程(转)
add by zhj: 装饰器的作用是将代码中可以独立的功能独立出来,实现代码复用,下面那个用于统计函数运行时间的装饰器就是很好的例子,我们不用修改原有的函数和调用原有函数的地方,这遵循了开闭原则.装 ...
随机推荐
- 阿里云composer 镜像
2019年12月2日13:54:32 https://developer.aliyun.com/composer 阿里云的镜像更新时间比较及时 本镜像与 Packagist 官方实时同步,推荐使用最新 ...
- ubantu系统安装ssh
ssh连接ubantu系统 描述:新安装的ubantu系统,ssh连接发现22端口拒绝,登陆服务器发现没有ssh 1.安装ssh服务 apt-get install openssh-server 报错 ...
- PHP urlencode空格被转为+的问题
我想既然各位点进来,绝大数是因为你遇到了空格被转为+号所带来的坑 不过没关系,解决方案很简单:使用rawurlencode()来进行编码即可~此函数遵循RFC 3986标准,空格会被转为%20 同时, ...
- python入门之与用户交互
目录 一.程序与用户交互 1.1 什么是与用户交互 1.2 为什么要与用户交互 1.3 如何与用户交互 1.4 python2和python3中input的区别 1.4.1 python3中的inpu ...
- 如何理解JavaScript的原型和原型链
在现在的业务开发中,应该很少人在写原生JavaScript了,大家都一股脑地扑在各个框架上.本来,这些框架对于业务和开发者来说是一种福音,减少了各种各样的开发痛点,但是带来的负面问题就是对于开发者来说 ...
- CSS选择符、伪类、层叠
主题,架子(时间架子,空间架子,三角架),素材. CSS 三种方式 行内样式 嵌入样式 链接样式 上下文选择符 祖父 孙 p em {color:red;} 父 子 p > em {color: ...
- 将网页html文件离线下载保存到本地的方法
(1)复制想要离线的网页的网址: 范例:http://bbs.xyaz.cn/thread-52540-1-1.html (2)将网址放入迅雷中,让其将html文件下载下来. (3)下载结果
- Linux crontab 查看所有用户的crontab任务
查看所有用户的crontab任务 - mlzhu007的专栏 - CSDN博客 https://blog.csdn.net/mlzhu007/article/details/81662091 以roo ...
- Windows10无法访问局域网文件夹
给目录guest用户,并启用guest 最近硬盘存储不开资料在同学的电脑存储了然后使用Windows提供的共享文件夹功能提供文件访问,可是今天上午一不小心把系统玩挂了重新安装了Windows10专业工 ...
- DRF框架(六)——三大认证组件之认证组件、权限组件
drf认证组件 用户信息表 from django.db import models from django.contrib.auth.models import AbstractUser class ...