[置顶] Android AOP 实践笔记
本文同步自wing的地方酒馆
最近博客更新越来越慢了,有两方面原因:
1.没啥好写的。
2.应该沉下心好好沉淀自己,积累一些东西,博客写的太频繁有”刷博客“之嫌,还容易浮躁。
浮躁是大忌 ,所以还是沉下心好好学吧。
网上已经有了很多类似的文章,这里再写一次是为了自己当做笔记,主要是对APT,AspectJ、Javassist的简单实用进行记录,方便以后翻阅。
AOP是什么这里不多作解释了,个人理解总结下来就是相对于各个垂直深入的业务逻辑,每个业务逻辑深度的某个层面他们有需要共同的特征,此时对这种特征进行统一的处理,也就是所谓的AOP(欢迎拍砖哈,技术在讨论中提升)
主要应用场景:
- 权限检查
- 日志记录
- 性能监控
- 埋点操作
Android 下一些可以进行AOP的工具
APT
在编译时生成 .java 文件。
代表作品 ButterKnife 、 DataBinding、 EventBus3、Dagger2 等。
AspectJ
在.java编译为.class的时候,进行代码注入。
代表作品: Hugo
Javassist
对已经编译好的class文件进行操作。
代表作品: 各类热修复框架(为了解决类校验问题)。
各个工具操作时机图
这里盗一张图。原图地址:http://www.jianshu.com/p/dca3e2c8608a
具体用法
APT
APT是编译时生成代码的技术, 主要用到了注解 以及处理注解的Process
这里我写一个简单的小例子,来展示如何使用APT,这个例子类似于MVPHelper的功能,但其实是没有什么乱用的,只是展示而已。
- 建立一个module 用于声明注解。
这里Contract注解,是为了标注一个Activity需要使用MVP模式。并且需要自动生成MVP代码。
- 再建立另一个module 用于处理这些注解。
注意这里必须是java库,也就是说gradle要apply java 插件,否则将引用不到javax包下的内容。
这个时候,我们只需要让ConrtactProcessor 继承 AbstractProcess,并且实现process函数去处理这个注解即可。
这里生成代码使用了Javapoet, 我们的目标是在Activity上面使用@Contract注解自动生成MVP代码,并且@Inject自动注入presenter,如下图:
这些红掉的代码,就是我们想要利用APT生成的代码,@Inject 用于表示注入mPresenter,这样就不用我们自己new了,当然这里是最简单的注入展示。 我们反过来想想,想让这些代码可以工作,生成的代码应该是怎样的。生成的代码路径如下所示:
MVP部分的代码不多说,来说一说presenter是如何注入的,其实很简单:
结合上面红色的代码看,应该会一目了然吧。
关于如何生成代码,只需要在process方法中使用javapoet即可,代码比较简单繁琐,这里就不贴了,有需要的可以到文章尾部的链接查看代码。
AspetJ
AspetJ的引入比较简单,主要是沪江公司对AspetJ进行了一些Android方面的适配。
在gradle添加
classpath 'com.hujiang.aspectjx:gradle-android-plugin-aspectjx:1.0.10'
以及
apply plugin: 'android-aspectjx'
使用的时候,只需要新建一个类,并且使用@Aspect注解,即可对需要hook的类生效,并且无需直接使用。
因为在看这个之前有在用Xposed,所以感觉两个很像,上手很快。
我们将要使用这个工具实现Activity 启动时间的监控,以及登录权限管理的注入,以往判断用户登录往往需要每个函数都判断一下最后执行逻辑,其实这完全可以注入进去,就像”切面“所说,需要登录的地方,一刀切。
实现Activity启动时间监控,这里写简单一点,单纯的从onCreate开始到onResume结束进行计时操作。
另外一个是登录检验操作,我们理想的事情是给一个函数添加一个注解,并且这个注解来判断是否登录执行相应的转跳提示操作。
示意如下,比如onResume需要判断是否登录,只需要一个注解
我们把需要的逻辑判断写在@AspetJ 注解的类里即可。
这样不管是埋点还是性能监控还是登录权限检验,都可以异常方便的执行。再也不像原先那样麻烦了。
Javassist
这个需要结合自定义gradle plugin一起操作,大家都知道apk编译的时候,先把java编译为class文件,接下来会变为dex文件,gradle提供了transform api,可以让我们class变为dex之前做任何想做的事情。
首先建立一个buildSrc的module,这里面创建的类都是groovy的类,所以扩展名要写groovy。至于内容嘛。。因为兼容java 随便你咯-。-
创建一个Plugin,叫做Regsiter, 只需要让他implement Plugin 插件即可, 此时重写apply方法,就可以在主工程中apply这个插件。
另外我们需要结合transform, 所以要给android插件注册一下transform
在transform里,我们就可以对所有文件进行操作了
ClassInjector 主要是使用Javassist进行对class文件的改变操作。
值得注意的是,如果操作的过程中需要使用android sdk内容,需要手动将 android.jar添加到 ClassPool里面。否则会提示找不到类的情况。
本文涉及Demo代码地址
https://github.com/githubwing/AopDemo
欢迎加入Android地方酒馆(425983695)一起研究Android技术。
参考文章
1.http://www.jianshu.com/p/dca3e2c8608a
2.http://blog.csdn.net/eclipsexys/article/details/54425414
3.http://blog.csdn.net/u010386612/article/details/51131642
[置顶] Android AOP 实践笔记的更多相关文章
- [置顶] Android开发笔记(成长轨迹)
分类: 开发学习笔记2013-06-21 09:44 26043人阅读 评论(5) 收藏 Android开发笔记 1.控制台输出:called unimplemented OpenGL ES API ...
- [置顶]
Deep Learning 学习笔记
一.文章来由 好久没写原创博客了,一直处于学习新知识的阶段.来新加坡也有一个星期,搞定签证.入学等杂事之后,今天上午与导师确定了接下来的研究任务,我平时基本也是把博客当作联机版的云笔记~~如果有写的不 ...
- [置顶] Linux信号相关笔记
最近又温习了一遍Linux中的信号知识,发现有很多东西以前没有注意到,就通过这篇博客记录一下,巩固一下知识点. 一,信号基础: 信号是什么?为了回答这个问题,首先要从异常说起,这里的异常不是指c++/ ...
- [置顶] Android AlarmManager实现不间断轮询服务
在消息的获取上是选择轮询还是推送得根据实际的业务需要来技术选型,例如对消息实时性比较高的需求,比如微博新通知或新闻等那就最好是用推送了.但如果只是一般的消息检测比如更新检查,可能是半个小时或一个小时一 ...
- [置顶] [Android源码分析]inquiry result引起的上层变化分析
在上一篇文章中,我们详细分析了android是如何解析蓝牙反馈上来的搜索到的设备信息,本文将会继续分析这些信息到了上层之后是如何处理. 8.inquiry result引起的上层变化 我们知道inqu ...
- [置顶] Android四大组件之BroadcastReceiver
Android四大组件之BroadcastReceiver Broadcast Receiver 广播接收器,是一种负责接收广播消息并对消息做出响应的组件,和Service一样并不提供与用户交互的UI ...
- [置顶] Android图片异步加载之Android-Universal-Image-Loader
将近一个月没有更新博客了,由于这段时间以来准备毕业论文等各种事务缠身,一直没有时间和精力沉下来继续学习和整理一些东西.最近刚刚恢复到正轨,正好这两天看了下Android上关于图片异步加载的开源项目,就 ...
- 【转】 [置顶] Android 通知栏Notification的整合 全面学习 (一个DEMO让你完全了解它)
在Android的应用层中,涉及到很多应用框架,例如:Service框架,Activity管理机制,Broadcast机制,对话框框架,标题栏框架,状态栏框架,通知机制,ActionBar框架等等. ...
- [置顶]
Android 状态栏那些小坑?
背景:因为之前老板上次问我我们的app能不能自定义上面的状态栏我说可以啊!当时没管,今天试了下果然很多坑,之前github上也有很多大佬写了一个开源库有兴趣的可以点进去看下支持DrawLayout沉侵 ...
随机推荐
- 20145321 《Java程序设计》第9周学习总结
20145321 <Java程序设计>第9周学习总结 教材学习内容总结 第十六章 整合数据库 16.1 JDBC 1.JDBC简介: JDBC是Java联机数据库的标准规范,它定义一组标准 ...
- C++ 读取文件所有内容的方法
方法一 #include <fstream> #include <string> #include <iostream> using namespace std; ...
- Objective C NSString 编码成URL 特殊字符处理
找了一下网上的教程都是使用类似以下代码,Xcode提示这个CoreFoundation不受ARC管理,所以折中的方式是添加__bridge. NSString *encodedValue = (__b ...
- Java循环跳转语句之 break
生活中,我们经常会因为某些原因中断既定的任务安排.如在参加 10000 米长跑时,才跑了 500 米就由于体力不支,需要退出比赛.在 Java 中,我们可以使用 break 语句退出指定的循环,直接执 ...
- [Spring]Spring Mvc实现国际化/多语言
1.添加多语言文件*.properties F64_en_EN.properties详情如下: F60_G00_M100=Please select data. F60_G00_M101=Are yo ...
- The tilde ( ~ ) operator in JavaScript
From the JavaScript Reference on MDC, ~ (Bitwise NOT) Performs the NOT operator on each bit. NOT a y ...
- 【IIS转】:解决IIS下localhost访问需要输入用户名和密码的问题
[摘要]安装完IIS后,我们可能会发现浏览器输入localhost访问时提示我们输入用户名和密码,本文介绍了这种问题的解决方法,方便站长们调试自己的程序. 在我们的WIN XP系统中安装了IIS,但是 ...
- [转载]宿主机为linux、windows分别实现VMware三种方式上网,Host-only win10+rhel7.2实现
研究一下虚拟机三种上网方式 转自:http://linuxme.blog.51cto.com/1850814/389691 一.VMware三种方式工作原理1 Host-only连接方式 让虚机具有与 ...
- HLSL实现简单的图像处理功能
由于对于dxva2解码得到的数据不宜copy回内存给CPU处理,所以最好的办法是在GPU上直接进行处理.D3D的像素着色器能够对像素直接进行操作,实现点运算极其简单方便,简单的卷积运算效果也非常好.但 ...
- 【SystemTap】 Linux下安装使用SystemTap源码安装SystemTap
转自 http://blog.csdn.net/zklth/article/details/6248558 文章 http://blog.csdn.net/zklth/archive/2010/09/ ...