android aspectj api,android- AspectJ 的接入使用

AspectJ 作为aop的著名工具,现在就让我们进行使用他,不逼逼。

接入有两种方式,一种是组件化式接入,一种是非组件化接入。组件化接入,就是当我们的项目是组件化开发时,有多个moudle。

非组件化接入:

第一步:在项目gradle中添加aspectJ的依赖

classpath 'org.aspectj:aspectjtools:1.8.6'

第二步:在app gradle中添加依赖和配置

implementation 'org.aspectj:aspectjrt:1.8.13'

import org.aspectj.bridge.IMessage

import org.aspectj.bridge.MessageHandler

import org.aspectj.tools.ajc.Main

final def log = project.logger

final def variants = project.android.applicationVariants

//在构建工程时,执行编织

variants.all { variant ->

if (!variant.buildType.isDebuggable()) {

log.debug("Skipping non-debuggable build type '${variant.buildType.name}'.")

return;

}

JavaCompile 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;

}

}

}

}

以上代码放到最下面就好了。

现在配置就完成了

第三步:添加测试:

**

* Created by malei on 2019/2/28.

*/

@Aspect //必须使用@AspectJ标注,这样class DemoAspect就等同于 aspect DemoAspect了

public class DemoAspect {

String TAG = "DemoAspect";

/*

@Pointcut:pointcut也变成了一个注解,这个注解是针对一个函数的,比如此处的logForActivity()

其实它代表了这个pointcut的名字。如果是带参数的pointcut,则把参数类型和名字放到

代表pointcut名字的logForActivity中,然后在@Pointcut注解中使用参数名。

基本和以前一样,只是写起来比较奇特一点。后面我们会介绍带参数的例子

*/

@Pointcut("execution(* com.ml.maskpro.ui.MainActivity.onCreate(..)) ||"

+"execution(* com.ml.maskpro.ui.MainActivity.onStart(..))")

public void logForActivity(){}; //注意,这个函数必须要有实现,否则Java编译器会报错

/*

@Before:这就是Before的advice,对于after,after -returning,和after-throwing。对于的注解格式为

@After,@AfterReturning,@AfterThrowing。Before后面跟的是pointcut名字,然后其代码块由一个函数来实现。比如此处的log。

*/

@Before("logForActivity()")

public void log(JoinPoint joinPoint){

//对于使用Annotation的AspectJ而言,JoinPoint就不能直接在代码里得到多了,而需要通过

//参数传递进来。

Log.e(TAG, joinPoint.toShortString() + " aop拦截");

}

}

这样,我们的MainActivity的onCreate()方法被触发的时候,我们就会进行拦截,并打印指定的内容。

组件化接入

使用组件化的方式接入,就避免了重复编写代码的问题。

接下来,用几步就完成我们的组件化接俄入吧。

第一步:首先让我们创建一个moudle -->  aspectJlib

1)moudle 里面的东西都删除(除了build.gradle,但是要被gradle里面的所有内容删除)

2)在aspectJlib里面新增一个“src”文件夹,往src文件夹新增main文件夹,再往main文件夹新增groovy和resources文件夹

3)resources目录下新建文件夹META-INF,META-INF文件夹下新建gradle-plugins文件夹。

4)在groovy目录下新建项目包名,就像Java包名那样。

f0d4558534f8463fc462b24576df413a.png

第二步:打开Module下的build.gradle文件,输入

apply plugin: 'groovy'

apply plugin: 'maven'

dependencies {

implementation gradleApi()//gradle sdk

implementation localGroovy()//groovy sdk

implementation 'com.android.tools.build:gradle:3.0.1'

implementation 'org.javassist:javassist:3.20.0-GA'

implementation 'org.aspectj:aspectjtools:1.8.13'

}

//上传到仓库

uploadArchives {

repositories.mavenDeployer {

pom.groupId = 'com.ml.pro'

pom.artifactId = 'aspectjlib'

pom.version = '1.0.0'

repository(url: uri('../repo'))

}

}

repositories {

jcenter()

}

uploadArchives闭包里面配置的是将插件发布到本地仓库。然后maven本地仓库的目录就是当前项目目录下的repo目录。

第三步:在groovy下的包名下新建一个文件,命名为AspectjPlugin.groovy

package com.ml.pro

import org.aspectj.bridge.IMessage

import org.aspectj.bridge.MessageHandler

import org.aspectj.tools.ajc.Main

import org.gradle.api.Plugin

import org.gradle.api.Project

/**

* @使用ajc编译java代码 , 同 时 织 入 切 片 代 码

* 使用 AspectJ 的编译器(ajc,一个java编译器的扩展)

* 对所有受 aspect 影响的类进行织入。

* 在 gradle 的编译 task 中增加额外配置,使之能正确编译运行。

*/

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;

}

}

}

}

}

}

第四步:在resources/META-INF/gradle-plugins目录下新建一个 AspectjPlugin.properties 文件,命名就是刚才创建 .groovy 的名字.

在里面输入:

implementation-class=com.ml.pro.AspectjPlugin

第五步:右侧的gradle Toolbar就会在module下多出一个task,点击uploadArchives这个Task,就会在项目下多出一个repo目录,里面存着这个gradle插件。

这样切面组件的组件化部分就完成了。现在就可以提供给其他module使用了。

第六步:在项目 gadle中添加

buildscript {

repositories {

...

maven { url uri('repo') } //插件仓库路径

}

dependencies {

...

classpath 'com.ml.pro:aspectjlib:1.0.0' //插件

}

}

第七步:先Rebuild Project,最后在app下的build.gradle添加配置

apply plugin: 'AspectjPlugin'

同时也要添加依赖(但是在实际编码时,没有添加依然可以使用):

compile 'org.aspectj:aspectjrt:1.8.9'

这样就完成了,我们就进行测试:

/**

* Created by malei on 2019/2/28.

*/

@Aspect

public class AspectTest {

final String TAG = AspectTest.class.getSimpleName();

/**

* 在MainActivity的所有生命周期的方法中打印log

* @param joinPoint

* @throws Throwable

*/

@Before("execution(* *..MainActivity+.on**(..))")

public void method(JoinPoint joinPoint) throws Throwable {

MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();

String className = joinPoint.getThis().getClass().getSimpleName();

Log.e(TAG, "class:" + className);

Log.e(TAG, "method:" + methodSignature.getName());

}

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值