Android中的AOP
来源:互联网 发布:qq会员免费开通软件 编辑:程序博客网 时间:2024/06/06 17:32
说一件开心的事情,我的这篇文章_AOP编程将被刊登在 鸿洋的微信公众号上,开心ing…
回归正题了。
来源:知乎 欲眼熊猫
面向切面编程(AOP是Aspect Oriented Program的首字母缩写) ,我们知道,面向对象的特点是继承、多态和封装。而封装就要求将功能分散到不同的对象中去,这在软件设计中往往称为职责分配。实际上也就是说,让不同的类设计不同的方法。这样代码就分散到一个个的类中去了。这样做的好处是降低了代码的复杂程度,使类可重用。 但是人们也发现,在分散代码的同时,也增加了代码的重复性。什么意思呢?比如说,我们在两个类中,可能都需要在每个方法中做日志。按面向对象的设计方法,我们就必须在两个类的方法中都加入日志的内容。也许他们是完全相同的,但就是因为面向对象的设计让类与类之间无法联系,而不能将这些重复的代码统一起来。 也许有人会说,那好办啊,我们可以将这段代码写在一个独立的类独立的方法里,然后再在这两个类中调用。但是,这样一来,这两个类跟我们上面提到的独立的类就有耦合了,它的改变会影响这两个类。那么,有没有什么办法,能让我们在需要的时候,随意地加入代码呢?这种在运行时,动态地将代码切入到类的指定方法、指定位置上的编程思想就是面向切面的编程。 一般而言,我们管切入到指定类指定方法的代码片段称为切面,而切入到哪些类、哪些方法则叫切入点。有了AOP,我们就可以把几个类共有的代码,抽取到一个切片中,等到需要时再切入对象中去,从而改变其原有的行为。这样看来,AOP其实只是OOP的补充而已。OOP从横向上区分出一个个的类来,而AOP则从纵向上向对象中加入特定的代码。有了AOP,OOP变得立体了。如果加上时间维度,AOP使OOP由原来的二维变为三维了,由平面变成立体了。从技术上来说,AOP基本上是通过代理机制实现的。 AOP在编程历史上可以说是里程碑式的,对OOP编程是一种十分有益的补充。
* 在运行时,动态地将代码切入到类的指定方法、指定位置上的编程思想就是面向切面的编程。*
场景:
分离复杂度,逻辑事务与非逻辑事务分离
具体场景有:
* 日志收集;
* 权限验证;
* 数据验证;
* 监控;
* 更多
基本需要了解的概念
Join Points
JPoints就是程序运行时的一些执行点。那么,一个程序中,哪些执行点是JPoints呢?比如:
l 一个函数的调用可以是一个JPoint。比如Log.e()这个函数。e的执行可以是一个JPoint,而调用e的函数也可以认为是一个JPoint。
l 设置一个变量,或者读取一个变量,也可以是一个JPoint。比如Demo类中有一个debug的boolean变量。设置它的地方或者读取它的地方都可以看做是JPoints。
我们经常看到的依赖注入经常是这样用的:
@BindView(R.id.textView_commend_2) CommonTabLayout tl_2; @OnClick(R.id.textView_commend_2) public void onClickAdd() { //在该方法运行时 也是执行点 }
上面代码的作用相信大家都知道,那么在这里 设置变量tl_2
时是执行点,声明方法onClickAdd
也是执行点。
甚至 我做一个操作 ,比如点击一个按钮,这个按钮会执行onClickAdd
方法,那么在我调用 onClickAdd
方法之前可以是执行点、在执行onCLickAdd
的过程中也可以是执行点。
这段话说的有点绕口,如果没有表达清楚,请见谅。
Pointcuts
Pointcuts是什么呢? Pointcuts的功能 是从众多的 JoinPoint中找到指定的执行点;
在上面的代码中 我可以通过注解拿到 变量和方法;然而通过上面的解释我们知道一个变量或者方法存在好多个执行点,我方法在即将执行之前是执行点,执行过程中也可以是个执行点,set变量是执行点,get变量也是执行点,那么我拿到了变量或者方法,我在什么时候做事情呢? 我通过什么判断呢? Pointcuts就是做这个事情的。
* 白话:pointCuts 的作用是找到指定的注解,通过注解拿到声明的 变量或者方法,然后设置 变量/方法 在指定的执行点 joinPoint 。*
然后我们就可以在 指定的执行点下做我们自定义的一系列动作。
* Pointcuts的目标是提供一种方法使得开发者能够选择自己感兴趣的JoinPoints。*
pointcuts中最常用的选择条件和Joinpoint的类型密切相关
题目: 小明的旧娃娃质量不好,没用几下折腾几下就破掉了,小明很郁闷,然后小明去买新娃娃,这个店家给他推荐了一个苍老师版本的娃娃,小明在付款的时候突然想到旧娃娃的质量不好,提出要验验货。‘
* 答案:*
@Pointcut("execution(@com.wenld.aspectjdemo.买娃娃 * *(..))") public void executionAspectJ() { 验货...嘿嘿嘿 if(验货通过) 买 }
声明我们要找的买娃娃
注解,注解找到的方法 选择苍老师款+付款
(execution
)的时候 ,executionAspectJ
验验货….
advice和aspect
恭喜,看到这个地方来,AspectJ的核心部分就掌握一大部分了。现在,我们知道如何通过pointcuts来选择合适的JPoint。那么,下一步工作就很明确了,选择这些JPoint后,我们肯定是需要干一些事情的。比如前面例子中的 before 小明验货之类的。这其实JPoint在执行前,执行后,都执行了一些我们设置的代码。
advice的类型
关键词 说明 示例 before() before advice 表示在JPoint执行之前,需要干的事情 after() after advice 表示JPoint自己执行完了后,需要干的事情。 after():returning(返回值类型) after():throwing(异常类型) returning和throwing后面都可以指定具体的类型,如果不指定的话则匹配的时候不限定类型 假设JPoint是一个函数调用的话,那么函数调用执行完有两种方式退出,一个是正常的return,另外一个是抛异常。 注意,after()默认包括returning和throwing两种情况 返回值类型 around() before和around是指JPoint执行前或执行后备触发,而around就替代了原JPoint around是替代了原JPoint,如果要执行原JPoint的话,需要调用proceed
在Android 中AOP工具和库
AspectJ: 一个 JavaTM 语言的面向切面编程的无缝扩展(适用Android)。
Javassist for Android: 用于字节码操作的知名 java 类库 Javassist 的 Android 平台移植版。
DexMaker: Dalvik 虚拟机上,在编译期或者运行时生成代码的 Java API。
ASMDEX: 一个类似 ASM 的字节码操作库,运行在Android平台,操作Dex字节码。
在Android 中AOP的使用
这里使用 AspectJ:
* 功能强大
* 支持编译期和加载时代码注入
* 易于使用
先要装ASpectJ环境
其中还要在gradle内配置一些东西,具体详细请看代码,这里就不贴了。
注解类 AspectJAnnotation
@Target(ElementType.METHOD)@Retention(RetentionPolicy.RUNTIME)public @interface AspectJAnnotation { String value();}
执行类AspectJTest
/** * <p/> * Author: 温利东 on 2017/3/2 16:07. * blog: http://blog.csdn.net/sinat_15877283 * github: https://github.com/LidongWen */@Aspectpublic class AspectJTest { private static final String TAG = "tag00"; @Pointcut("execution(@com.wenld.aspectjdemo.AspectJAnnotation * *(..))") public void executionAspectJ() { } @Around("executionAspectJ()") public Object aroundAspectJ(ProceedingJoinPoint joinPoint) throws Throwable { MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature(); Log.i(TAG, "aroundAspectJ(ProceedingJoinPoint joinPoint)"); AspectJAnnotation aspectJAnnotation = methodSignature.getMethod().getAnnotation(AspectJAnnotation.class); String permission = aspectJAnnotation.value(); if(permission.equals("权限A")) { Object result=joinPoint.proceed(); Log.i(TAG, "有权限:"+permission); return result; } return ""; }}
MainActivity
@AspectJAnnotation(value = "权限A") public String test() { Log.i(TAG, "检查权限"); return "test"; }
示例源码地址:https://github.com/LidongWen/AspectJDemo/tree/master
* 一些资料地址:*
https://en.wikipedia.org/wiki/AOP
l http://www.eclipse.org/aspectj/ <=AspectJ官方网站
l http://www.eclipse.org/aspectj/doc/released/runtime-api/index.html <=AspectJ类库参考文档,内容非常少
l http://www.eclipse.org/aspectj/doc/released/aspectj5rt-api/index.html <=@AspectJ文档,以后我们用Annotation的方式最多。
AspectJ语法
http://www.eclipse.org/aspectj/doc/released/quick5.pdf 或者官方的另外一个文档也可以:
http://www.eclipse.org/aspectj/doc/released/progguide/semantics.html
各位同学,目前已经转入至简书,欢迎来搞事情
简书地址: http://www.jianshu.com/users/99f514ea81b3/timeline
github: LidongWen
人生得意须尽欢, 桃花坞里桃花庵
点个关注呗,对,不信你点试试?
- Android 中的 AOP 编程
- Android中的AOP编程
- Android 中的 AOP 编程
- Android中的AOP编程
- Android 中的 AOP 编程
- android中的aop
- Android 中的 AOP 编程
- Android中的AOP
- Android中的AOP编程
- AOP在Android中的应用
- 【翻译】Android中的AOP编程
- AOP在Android中的使用(作为依赖库)
- 归纳AOP在Android开发中的几种常见用法
- Spring 中的 AOP
- Spring 中的 AOP
- SSH中的Aop使用
- spring中的aop术语
- Aop 中的相关概念
- android studio下的NDK开发详解(一)
- 67. Add Binary
- 关于深度搜索棍子的题
- [Keil] MDK5 集成开发环境搭建与注册破解
- (2)FPQuant JHipster_运行Java服务器
- Android中的AOP
- 待查
- 手机信息界面的布局编写
- postman传json串,以及postman官方文档
- 有限制条件的深度优先遍历生成全排列
- c++版 mulSpectrums
- 内存紧张以及程序进入后台
- C#中连接Oracle数据库时提示OCIEnvCreate 失败,返回代码为 -1,但错误消息文本不可用。
- 40G以太网连接中的光模块解决方案