前言

本章节目的不是详细的介绍AspectJ的细节,而是最近项目用到了AspectJ,通过一个简单例子来看下定义切片以及使用切片的流程是怎样的。

AspectJ

AspectJ 是使用最为广泛的 AOP 实现方案,适用于 Java 平台,官网地址:http://www.eclipse.org/aspectj/ 。AspectJ 是在静态织入代码,即在编译期注入代码的。

AspectJ 提供了一套全新的语法实现,完全兼容 Java(跟 Java 之间的区别,只是多了一些关键词而已)。同时,还提供了纯 Java 语言的实现,通过注解的方式,完成代码编织的功能。因此我们在使用 AspectJ 的时候有以下两种方式:

使用 AspectJ 的语言进行开发

通过 AspectJ 提供的注解在 Java 语言上开发

因为最终的目的其实都是需要在字节码文件中织入我们自己定义的切面代码,不管使用哪种方式接入 AspectJ,都需要使用 AspectJ 提供的代码编译工具 ajc 进行编译。

在 Android Studio 上一般使用注解的方式使用 AspectJ,因为 Android Studio 没有 AspectJ 插件,无法识别 AspectJ 的语法(不过在 Intellij IDEA 收费版上可以使用 AspectJ 插件),所以后面的语法说明和示例都是以注解的实现方式。

常用术语

在了解AspectJ的具体使用之前,先了解一下其中的一些基本的术语概念,这有利于我们掌握AspectJ的使用以及AOP的编程思想。

JoinPoints

JoinPoints(连接点),程序中可能作为代码注入目标的特定的点。在AspectJ中可以作为JoinPoints的地方包括:

PointCuts

PointCuts(切入点),其实就是代码注入的位置。与前面的JoinPoints不同的地方在于,其实PointCuts是有条件限定的JoinPoints。比如说,在一个Java源文件中,会有很多的JoinPoints,但是我们只希望对其中带有@debug注解的地方才注入代码。所以,PointCuts是通过语法标准给JoinPoints添加了筛选条件限定。

Advice

Advice(通知),其实就是注入到class文件中的代码片。典型的 Advice 类型有 before、after 和 around,分别表示在目标方法执行之前、执行后和完全替代目标方法执行的代码。

Aspect

Aspect(切面),Pointcut 和 Advice 的组合看做切面。

Weaving

注入代码(advices)到目标位置(joint points)的过程

接下来通过项目看一下实践过程

在annotation里定义注解

@Retention(RetentionPolicy.CLASS)

@Target(ElementType.METHOD)

public @interface CheckLogin {

}

在android studio的android工程中使用AspectJ的时候,我们需要在项目的build.gradle的文件中添加一些配置:

dependencies {

classpath 'org.aspectj:aspectjtools:1.8.9'

...

}

在新建module里定义AspectjPlugin,也可以直接写到gradle里面,固定写法没啥说的

public class AspectjPlugin implements Plugin {

void apply(Project project) {

project.dependencies {

compile 'org.aspectj:aspectjrt:1.8.9'

}

final def log = project.logger

log.error "========================";

log.error "Aspectj切片开始编织Class!";

log.error "========================";

project.android.applicationVariants.all { variant ->

def javaCompile = variant.javaCompile

javaCompile.doLast {

String[] args = ["-showWeaveInfo",

"-1.8",

"-inpath", javaCompile.destinationDir.toString(),

"-aspectpath", javaCompile.classpath.asPath,

"-d", javaCompile.destinationDir.toString(),

"-classpath", javaCompile.classpath.asPath,

"-bootclasspath", project.android.bootClasspath.join(File.pathSeparator)]

log.debug "ajc args: " + Arrays.toString(args)

MessageHandler handler = new MessageHandler(true);

new Main().run(args, handler);

for (IMessage message : handler.getMessages(null, true)) {

switch (message.getKind()) {

case IMessage.ABORT:

case IMessage.ERROR:

case IMessage.FAIL:

log.error message.message, message.thrown

break;

case IMessage.WARNING:

log.warn message.message, message.thrown

break;

case IMessage.INFO:

log.info message.message, message.thrown

break;

case IMessage.DEBUG:

log.debug message.message, message.thrown

break;

}

}

}

}

}

}

在app的build.gradle里面

import com.app.plugin.AspectjPlugin

apply plugin: AspectjPlugin

定义切片

@Aspect

public class CheckLoginAspect {

@Pointcut("execution(@com.app.annotation.aspect.CheckLogin * *(..))")//方法切入点

public void methodAnnotated() {

}

@Around("methodAnnotated()")//在连接点进行方法替换

public void aroundJoinPoint(ProceedingJoinPoint joinPoint) throws Throwable {

if (!SharedPreferenceUtil.isLogin()) {

Snackbar.make(AopApplication.getAppContext().getCurActivity().getWindow().getDecorView(), "请先登录!", Snackbar.LENGTH_LONG)

.setAction("登录", new View.OnClickListener() {

@Override

public void onClick(View view) {

SharedPreferenceUtil.setLogin(AopApplication.getAppContext(), true);

Toast.makeText(AopApplication.getAppContext(), "登录成功", Toast.LENGTH_SHORT).show();

}

}).show();

return;

}

joinPoint.proceed();//执行原方法

}

}

在MainActivity里面使用注解@CheckLogin,看下build/intermediates/classes编译出来的class里面的插入代码

@CheckLogin

public void doMarkDown()

{

JoinPoint localJoinPoint = Factory.makeJP(ajc$tjp_0, this, this);Object[] arrayOfObject = new

Object[2];arrayOfObject[0] = this;arrayOfObject[1] =

localJoinPoint;CheckLoginAspect.aspectOf().aroundJoinPoint(new

MainActivity.AjcClosure1(arrayOfObject).linkClosureAndJoinPoint(69648));

}

static final void doMarkDown_aroundBody0(MainActivity ajc$this, JoinPoint paramJoinPoint)

{

Toast.makeText(AopApplication.getAppContext(), , 1).show();

}

使用总结

1.定义注解

2.添加入口plugin或者直接写在gradle里

3.定义切片,设置@Pointcut使用execution来设置方法的切入点为com.app.annotation.aspect包下的CheckLogin

4.编写切片处理逻辑在Advice里,Advice就是我们插入的代码可以以何种方式插入,有Before 还有 After、Around

5.在项目里使用切片,达到在指定位置插入代码的目的,可以在具体项目里面同一种场景使用该注解达到处理切面的问题,大大减少了代码的书写,更加是AOP的具体体现,对OOP的一种弥补

最后

本章节只是介绍了少部分的AspectJ的使用,还是那句老话,AspectJ本身并没有技术难点,难的是怎么设计出好用的切面,无论是log还是监控日志都可以使用该方式进行尝试.

作为老司机,这是弯道超车的必备秘籍,天下武功、唯快不破!

android studio 中怎么写aspectj代码,Android AOP三剑客之AspectJ相关推荐

  1. android 模拟器应用未安装,当我在Android Studio中运行它时,Android应用程序未安装在模拟器或设备上...

    我正在开发Android应用程序.在我的应用程序中,我正在测试在设备和模拟器上运行的应用程序.这是我的第三个Android应用程序开发.当我开发其他应用程序时,应用程序会自动安装在设备上或模拟器上的启 ...

  2. 【我的Android进阶之旅】Android Studio 中 使用git提交代码报错:Can‘t commit changes from multiple changelists at once

    一.错误描述 今天在Android Studio中,Commit代码的时候报错了,然后解决了. 现在模拟复现下之前的错误,如下所示: 0 file committed, 2 files failed ...

  3. android studio 中怎么写aspectj代码,Android Studio 使用 AspectJ 实践AOP

    Android Studio 官方暂时不支持aspectJ,不过这里用的一款gradle插件 aspectjx 配置在project的build.gradle里配置插件dependencies { c ...

  4. android studio 中怎么写aspectj代码,AndroidStudio中 AspectJ 基础使用 简介

    AOP(Aspect Oriented Programming)切面编程在处理一些与业务逻辑无关,但在很多地方又不得不添加相关逻辑代码,可以很好的解决相关问题,比如在Android中有些地方需要打LO ...

  5. Android Studio中使用Git进行代码管理(分支、合并)

    打开Android Studio选择,选择从Git检出代码 也可以从VCS如下点击 去远程仓库复制地址,这里以码云Gitee第三方代码托管为例,类似Github的界面,点击右边复制项目地址 填一下配置 ...

  6. android studio中添加gif文件格式,利用Android Studio截屏和录制视频并转为gif

    前言:在写博客或者传项目到github上时放上一张gif图片更能表达出作者想要表达的内容,那么怎样可以方便的录制一张gif图片,就成了本篇博客要讨论的内容了. 这里使用Android Studio来制 ...

  7. android.mk if else,gradle - 如何在Android Studio中使用我自己的Android.mk文件 - SO中文参考 - www.soinside.com...

    [我正在Android.mk文件中定义一些变量(我正在为编译器传递一些标志),但是每次构建项目时,Android.mk都会被覆盖.我假设Gradle是负责任的,我应该去那里看看吗? 如何使用我自己的A ...

  8. android studio中的适配器,如何在Android Studio中测试回收器视图适配器

    有人可以帮我测试这个回收站视图适配器吗?我不想进行本地单元测试,但不知道如何开始? 以下是我的recyclerViewAdapter类: public class RecyclerViewAdapte ...

  9. Android编程权威指南笔记3:Android Fragment讲解与Android Studio中的依赖关系,如何添加依赖关系

    Android Fragment 当我在学习时,了解了Fragment词汇 Fragment是一种控制器对象,我就把所了解的简单说一下.activity可以派fragment完成一些任务,就是管理用户 ...

  10. Android Studio中模拟器的创建

    Android Studio中模拟器的创建 针对Android Studio没有勾选模拟器的下载或者是下载失败的情况的模拟器的创建过程 第一步:点击"Create device"创 ...

最新文章

  1. 充分理解表达式——《狂人C》习题解答2(第二章习题5)
  2. C语言-getopt函数
  3. pyinstaller打包后读不到配置文件的解决方法
  4. FCN全连接卷积网络(4)--Fully Convolutional Networks for Semantic Segmentation阅读(引言部分)
  5. 解决gdb 调试 core 文件函数名显示为问号的问题
  6. TensorFlow——基于Keras子类API的fashion-mnist数据集图像分类
  7. 安装中文版cacti监控华为交换机流量并实现95计费
  8. 电影票上的字是怎么消失的?
  9. JavaScript继承方式详解
  10. [AHK]双击Ctrl+C调用谷歌翻译!
  11. Pug/jade快速上手教程
  12. vue模板解析——源码演示
  13. 南阳oj 28 大数阶乘
  14. P2123 皇后游戏
  15. ORCAL计算司龄是否满一年
  16. 书记员计算机操作基础知识考试,书记员打字考试怎么考?有哪些形式?
  17. ctf(EasySQL)
  18. kinect for windows - 初认识
  19. 单片机c语言数码管程序,51单片机C语言程序(三)数码管
  20. java 电商锁库存实现_电商项目扣减库存方案

热门文章

  1. 第三方魔兽金币交易平台的影响力会很快地褪去
  2. 推荐一款焦点图jQuery插件 SlidesJs
  3. POJ 2406 Power Strings
  4. Windows Azure 基本操作手册
  5. 【COM范例】WM上获取短信内容,AcitiveX控件调用页面JS方法
  6. cppunit在vs2008下使用的环境搭建
  7. L2-003 月饼 (25 point(s))
  8. mysql awr 上海用户组_AWR-mysql教程-PHP中文网
  9. 怎么打包图片_房产也能批发!澳村庄40栋房打包出售,总价$175万,买了变村长!...
  10. 常见排序算法的python实现