Android 引入 AspectJ进行AOP开发的记录。

在不试用插件时,引入AspectJ到android工程

1. 在项目gradle引入插件: 

    dependencies {        ...        classpath 'org.aspectj:aspectjtools:1.9.5'        ...    }

2. 在创建aspect文件的包引入

dependencies {    ...    implementation 'org.aspectj:aspectjrt:1.9.5'    ...}

并在同gradle文件中,加入

import org.aspectj.bridge.IMessageimport org.aspectj.bridge.MessageHandlerimport org.aspectj.tools.ajc.Mainfinal def log = project.loggerfinal def variants = project.android.applicationVariantsvariants.all { variant ->    JavaCompile javaCompile    if (variant.hasProperty('javaCompileProvider')) {        //android gradle 3.3.0 +        javaCompile = variant.javaCompileProvider.get()    } else {        javaCompile = variant.javaCompile    }    def buildType = variant.buildType.name    javaCompile.doLast {        MessageHandler handler = new MessageHandler(true)        String[] javaArgs = [                "-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)        ]        new Main().run(javaArgs, handler)        String[] kotlinArgs = [                "-showWeaveInfo",                "-1.8",                "-inpath", project.buildDir.path + "/tmp/kotlin-classes/" + buildType,                "-aspectpath", javaCompile.classpath.asPath,                "-d", project.buildDir.path + "/tmp/kotlin-classes/" + buildType,                "-classpath", javaCompile.classpath.asPath,                "-bootclasspath", project.android.bootClasspath.join(File.pathSeparator)        ]        new Main().run(kotlinArgs, 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:                case IMessage.INFO:                    log.info message.message, message.thrown                    break                case IMessage.DEBUG:                    log.debug message.message, message.thrown                    break            }        }    }}

这样就成功引入AspectJ工具了,下一步编写Aspect文件。

3. 先实现自己的业务逻辑

package com.example.cheng.test;import android.annotation.SuppressLint;import android.os.Bundle;import android.widget.TextView;import com.example.common.DisplayMetricsUtil;import androidx.annotation.Nullable;import androidx.appcompat.app.AppCompatActivity;public class MainActivityJava extends AppCompatActivity {    @SuppressLint("SetTextI18n")    @Override    protected void onCreate(@Nullable Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        TextView text = findViewById(R.id.text);        text.measure(0, 0);        text.setText("text width: " + DisplayMetricsUtil.px2dp(this, text.getMeasuredWidth()));    }}

4. 再在同module下实现aspect文件 

package com.example.cheng.test;import org.aspectj.lang.JoinPoint;import org.aspectj.lang.annotation.After;import org.aspectj.lang.annotation.Aspect;import org.aspectj.lang.annotation.Pointcut;@Aspectpublic class MainActivityAspectJava extends BaseAspect {    @Pointcut("execution(* com.example.cheng.test.MainActivityJava.on*(..))")    public void mainPointCut() {    }    @After("mainPointCut()")    public void hookMain(JoinPoint joinPoint) throws Throwable {        log("java::" + joinPoint.getSignature().toLongString());    }    @Pointcut("call(* com.example.common.DisplayMetricsUtil.*(..))")    public void displayPointCut() {    }    @After("displayPointCut()")    public void hookDisplay(JoinPoint joinPoint) throws Throwable {        log("java::" + joinPoint.getSignature().toLongString());    }}

输出效果: 

 

补充记录:

1. 因为kotlin文件编译出的.class文件路径与java不同,所以需要额外为aspect tool指定kotlin的路径。

        String[] kotlinArgs = [                "-showWeaveInfo",                "-1.8",                "-inpath", project.buildDir.path + "/tmp/kotlin-classes/" + buildType,                "-aspectpath", javaCompile.classpath.asPath,                "-d", project.buildDir.path + "/tmp/kotlin-classes/" + buildType,                "-classpath", javaCompile.classpath.asPath,                "-bootclasspath", project.android.bootClasspath.join(File.pathSeparator)        ]        new Main().run(kotlinArgs, handler)

 

待解决问题:

1. kotlin每次都需要clean build

2. 如何跨module实现aop weave,即在一个包中,可以通过pointcut切入其他module中的方法及其调用。

3. Java写的业务逻辑,kotlin的aspect文件能够对其织入;Kotlin写的业务逻辑,Java的Aspect文件不能对其织入。

更多相关文章

  1. Android编译环境
  2. 关于Android的prelink(Linux)
  3. Fedora 15下使用android ndk 编译ffmepg0.8.4
  4. android 学习笔记1
  5. Android处理9.png文件流程
  6. Android的多媒体框架OpenCore(PacketVideo)介绍
  7. Cordova 3.x 基础(13) -- 为Android(安卓)APK签名
  8. Android更新ADT到R17以后,不能用第三方jar包了
  9. 在android真机上使用sqlite3

随机推荐

  1. SQL Server 2005数据库还原错误的经典解
  2. SQL Server数据库复制失败的原因及解决方
  3. 通过格式良好的SQL提高效率和准确性
  4. 没有SQL Server数据库时如何打开.MDF文件
  5. SQL Server无日志恢复数据库(2种方法)
  6. SQL Server多表查询优化方案集锦
  7. 简析SQL Server数据库用视图来处理复杂的
  8. 详解SQL Server数据库链接查询的方式
  9. SQL编程之子查询及注意事项
  10. SQL Server数据库安装时常见问题解决方案