AndroidStudio 配置 AspectJ 环境实现AOP的方法

作者:皮卡搜 时间:2021-09-03 10:09:01 

昨天看了一段android配置aspectj实现AOP的直播视频,就试着自己配置了一下,可能是因为我自己的AndroidStudio环境的问题,碰到了不少的坑(其实还是因为对gradle理解的不多),但总归是配置好了,就分享一下。

试了两种方式,不过项目下的build.gradle,没什么变化,直接看一下代码吧:

build.gradle(项目下)


buildscript {
 ext {
   //android appcompat支持库版本
   androidSupportVersion = '26.1.0'
   //编译的 SDK 版本,如API20
   compileSdkVersion = 26
   //构建工具的版本,其中包括了打包工具aapt、dx等,如API20对应的build-tool的版本就是20.0.0
   buildToolsVersion = "26.0.2"
   //兼容的最低 SDK 版本
   minSdkVersion = 15
   //向前兼容,保存新旧两种逻辑,并通过 if-else 方法来判断执行哪种逻辑
   targetSdkVersion = 26
   //kotlin版本号
   kotlin_version = '1.2.10'

kotlinVersion = "org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version"
   appcompatV7 = "com.android.support:appcompat-v7:$androidSupportVersion"
   appcompatDesign = "com.android.support:design:$androidSupportVersion"
   constraintLayout = 'com.android.support.constraint:constraint-layout:1.0.2'
 }
 repositories {
   google()
   jcenter()
   mavenCentral()
 }
 dependencies {
   classpath 'com.android.tools.build:gradle:3.0.1'
   classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
   classpath 'org.greenrobot:greendao-gradle-plugin:3.2.1'
   // NOTE: Do not place your application dependencies here; they belong
   // in the individual module build.gradle files
   classpath 'org.aspectj:aspectjtools:1.8.13'
   classpath 'org.aspectj:aspectjweaver:1.8.13'
 }

}

allprojects {
 repositories {
   google()
   jcenter()
   mavenCentral()
 }
}

task clean(type: Delete) {
 delete rootProject.buildDir
}

看着一大堆,主要就是下面这几行配置,其他的是我自己项目中用到的,根据自己需要配置就行。


buildscript {
 repositories {
   mavenCentral()
 }
 dependencies {
   classpath 'org.aspectj:aspectjtools:1.8.13'
   classpath 'org.aspectj:aspectjweaver:1.8.13'
 }
}

repositories {
 mavenCentral()
}

其实这几行配置在app的build.gradle里也是可以的,但是因为项目下的build.gradle里已经有buildscript {}、allprojects {repositories{} },就配置在这里了。

然后有两种配置方式:

第一种

只有一个主Module app的情况下,配置app的build.gradle:


apply plugin: 'com.android.application'

apply plugin: 'kotlin-android'

apply plugin: 'kotlin-android-extensions'

apply plugin: 'org.greenrobot.greendao'

android {
 compileSdkVersion rootProject.ext.compileSdkVersion
 buildToolsVersion rootProject.ext.buildToolsVersion
 defaultConfig {
   applicationId "填入自己的applicationId"
   minSdkVersion rootProject.ext.minSdkVersion
   targetSdkVersion rootProject.ext.targetSdkVersion
   versionCode 1
   versionName "1.0"
   //Lambda配置
//    jackOptions.enabled = true
//    android.compileOptions.sourceCompatibility 1.8
   buildConfigField "boolean", "LOG", "true"// 显示Log
   testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
   //支持矢量图
   vectorDrawables.useSupportLibrary = true
   ndk {
     //选择要添加的对应cpu类型的.so库。
     abiFilters 'armeabi', 'armeabi-v7a', 'arm64-v8a', 'x86', 'x86_64', 'mips', 'mips64'
   }
 }

buildTypes {
   release {
     minifyEnabled false
     buildConfigField "boolean", "LOG", "false"// 显示Log
     proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
   }

}

//Lambda配置
 compileOptions {
   sourceCompatibility JavaVersion.VERSION_1_8
   targetCompatibility JavaVersion.VERSION_1_8
 }

dataBinding {
   enabled true
 }

greendao {
   schemaVersion 1//数据库版本号
   daoPackage 'com.test.qby.newtestapplication.greendao'//设置DaoMaster、DaoSession、Dao包名
   targetGenDir 'src/main/java'//设置DaoMaster、DaoSession、Dao目录
   //targetGenDirTest:设置生成单元测试目录
   //generateTests:设置自动生成单元测试用例
 }

lintOptions {
   abortOnError true
 }

}

dependencies {
 implementation fileTree(include: ['*.jar'], dir: 'libs')
 implementation rootProject.ext.kotlinVersion
 implementation rootProject.ext.appcompatV7
 implementation rootProject.ext.constraintLayout
 compile rootProject.ext.appcompatDesign
 testImplementation 'junit:junit:4.12'
 androidTestImplementation 'com.android.support.test:runner:1.0.1'
 androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1'
 compile 'jp.wasabeef:glide-transformations:3.0.1'
 // If you want to use the GPU Filters
 compile 'jp.co.cyberagent.android.gpuimage:gpuimage-library:1.4.1'
 //腾讯bugly
 compile 'com.tencent.bugly:crashreport:latest.release'
 compile 'com.tencent.bugly:nativecrashreport:latest.release'
 //retrofit
 compile 'com.squareup.retrofit2:retrofit:2.3.0'
 compile 'com.squareup.retrofit2:converter-gson:2.3.0'
 compile 'com.squareup.retrofit2:adapter-rxjava2:2.3.0'
 compile 'com.squareup.okhttp3:logging-interceptor:3.9.0'
 //rxJava
 compile 'io.reactivex.rxjava2:rxandroid:2.0.1'
 // Because RxAndroid releases are few and far between, it is recommended you also
 // explicitly depend on RxJava's latest version for bug fixes and new features.
 compile 'io.reactivex.rxjava2:rxjava:2.1.8'
 //greenDao
 compile 'org.greenrobot:greendao:3.2.0'
 //换肤功能
 compile 'com.zhy:changeskin:4.0.2'
 //AOP面向切面编程,加入这行就不用在libs下引入jar包了,不然要写成compile file(libs/aspectjrt.jar)
 compile 'org.aspectj:aspectjrt:1.8.13'
}
/*
//在项目下配置了,此处就不需要了
buildscript {
 repositories {
   mavenCentral()
 }
 dependencies {
   classpath 'org.aspectj:aspectjtools:1.8.13'
   classpath 'org.aspectj:aspectjweaver:1.8.13'
 }
}

repositories {
 mavenCentral()
}
*/

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.5",
            "-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
     }
   }
 }
}

这一个gradle主要的东西就是这些:


//AOP面向切面编程,加入这行就不用在libs下引入jar包了,不然要写成compile file(libs/aspectjrt.jar)
compile '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.5",
            "-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
     }
   }
 }
}

下面那一堆是用命令在编译最后做一些关联的,具体的我也不懂,只管加上好了。

第二种

有多个module都需要用到aspectj,特别是组件开发的情况下,不可能每个module都配置一下,所以就需要新建一个aspectj的module作为项目的library。

app下build.gradle需要修改:


//AOP面向切面编程,加入这行就不用在libs下引入jar包了,不然要写成compile file(libs/aspectjrt.jar)
compile 'org.aspectj:aspectjrt:1.8.13'

去掉,改为


implementation project(':aspectjlib')

不过上面这句在你添加module依赖的时候会自动生成。

新建library的build.gradle配置如下:


apply plugin: 'com.android.library'

android {
 compileSdkVersion rootProject.ext.compileSdkVersion
 buildToolsVersion rootProject.ext.buildToolsVersion
 defaultConfig {
   minSdkVersion rootProject.ext.minSdkVersion
   targetSdkVersion rootProject.ext.targetSdkVersion
   versionCode 1
   versionName "1.0"

testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"

}

buildTypes {
   release {
     minifyEnabled false
     proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
   }
 }

}

dependencies {
 implementation fileTree(dir: 'libs', include: ['*.jar'])

implementation rootProject.ext.appcompatV7
 testImplementation 'junit:junit:4.12'
 androidTestImplementation 'com.android.support.test:runner:1.0.1'
 androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1'
 //AOP
 compile 'org.aspectj:aspectjrt:1.8.13'
}

import org.aspectj.bridge.IMessage
import org.aspectj.bridge.MessageHandler
import org.aspectj.tools.ajc.Main

android.libraryVariants.all { variant ->
 JavaCompile javaCompile = variant.javaCompile
 javaCompile.doLast {
   String[] args = ["-showWeaveInfo",
            "-1.5",
            "-inpath", javaCompile.destinationDir.toString(),
            "-aspectpath", javaCompile.classpath.asPath,
            "-d", javaCompile.destinationDir.toString(),
            "-classpath", javaCompile.classpath.asPath,
            "-bootclasspath", android.bootClasspath.join(
       File.pathSeparator)]

MessageHandler handler = new MessageHandler(true)
   new Main().run(args, handler)

def log = project.logger
   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
     }
   }
 }
}

注意:下面那一堆跟app的gradle中的稍微有点区别,一个是module,一个是library,gradle中的东西不一样。

两种配置方式基本就是这样了,使用方法我也是刚了解一点,记录一下简单的计算性能的用法吧

自定义注解类:


package com.test.qby.aspectjlib.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
* Created by qby on 2018/1/26 0026.
* 自定义注解
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface IFirstAnnotation {
 String value();
}

@Target 注解目标,表示注解使用在什么地方,这里是METHOD方法;@Retention 保留策略,表示注解调用时机,这里RUNTIME运行时

切面类


import android.widget.Toast;
import com.test.qby.aspectjlib.annotation.IFirstAnnotation;
import com.test.qby.newtestapplication.app.MyApplication;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import java.lang.reflect.Method;
import java.lang.reflect.TypeVariable;
import java.util.Locale;

/**
* Created by qby on 2018/1/26 0026.
* 自定义注解行为
*/
@Aspect
public class MethodBehaviorAspect {
 private static final String TAG = "aspect_aby";

@Pointcut("execution(@com.test.qby.aspectjlib.annotation.IFirstAnnotation * *(..))")
 public void firstMethodAnnotationBehavior() {
 }

@Pointcut("execution(* com.test.qby.newtestapplication.ui.MainActivity.aspectClick(android.view.View))")
 public void secondMethodAnnotationBehavior() {
 }

@Around("firstMethodAnnotationBehavior()")
 public Object wavePointcutAround(ProceedingJoinPoint joinPoint) throws Throwable {

MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
   // 类名
   String className = methodSignature.getDeclaringType().getSimpleName();
   // 方法名
   String methodName = methodSignature.getName();
   // 功能名
   IFirstAnnotation behaviorTrace = methodSignature.getMethod()
       .getAnnotation(IFirstAnnotation.class);
   String value = behaviorTrace.value();
//    String value = "点击";
   long start = System.currentTimeMillis();
   Object result = joinPoint.proceed();
   long duration = System.currentTimeMillis() - start;
   Log.e(TAG, String.format("%s类中%s方法执行%s功能,耗时:%dms", className, methodName, value, duration));
   Toast.makeText(MyApplication.getContext(), String.format(Locale.CHINESE, "%s类中%s方法执行%s功能,耗时:%dms", className, methodName, value, duration), Toast.LENGTH_SHORT).show();
   return result;
 }
}

@Aspect指定切面类;@Pointcut切入点;@Around是切入方式Advice的一种,表示在切入点前后插入代码,还有@Before、@After;Pointcut语法,execution,表示根据Advice在执行方法内部代码前后插入代码,call,表示根据Advice在调用方法前后插入代码......

页面调用


@IFirstAnnotation("测试Aspect")
public void aspectClick(View view) {
  try {
    Thread.sleep(new Random().nextInt(1000));
  } catch (InterruptedException e) {
    e.printStackTrace();
  }
}

@IFirstAnnotation调用注解,()内部为在IFirstAnnotation中写的value的值,去掉value()后此处去掉()

注意:在MethodBehaviorAspect 类中如果有用到Context,可直接使用joinPoint.getTarget()类型转换成Context,这里是由于项目使用了databinding,部分getTarget()获取到的值不能强转为Context,所以这里用的MyApplication获取的Context

这只是个人的初步尝试,里面当然还有很多内容需要去学,刚看了CSDN上有人写的几篇关于AOP的内容,都挺详细的,给出其中一个地址,自己看吧:https://www.jb51.net/article/110560.htm

来源:http://www.jianshu.com/p/7d6b6f60e3f4

标签:Android,Studio,AOP,AspectJ
0
投稿

猜你喜欢

  • 基于C#实现磁性吸附窗体

    2022-09-04 07:04:51
  • Java实现List集合转树形结构的示例详解

    2021-11-11 10:48:33
  • Java绘制迷宫动画并显示的示例代码

    2022-04-06 22:37:45
  • Java简单实现约瑟夫环算法示例

    2023-04-04 09:59:41
  • java 中如何实现 List 集合去重

    2023-10-07 07:54:06
  • Java中的这些骚操作你不能不知道!!!

    2022-07-08 12:28:14
  • Spring中IOC和AOP的深入讲解

    2023-11-19 10:20:59
  • c# wpf使用GMap.NET类库,实现地图轨迹回放

    2023-04-20 06:46:27
  • 剑指Offer之Java算法习题精讲求和篇

    2022-04-07 14:05:36
  • java排查一个线上死循环cpu暴涨的过程分析

    2022-07-20 01:27:08
  • Unity解析gif动态图操作

    2022-05-27 08:16:43
  • MybatisPlus分页排序查询字段带有下划线的坑及解决

    2022-08-16 22:26:28
  • Spring Boot整合Web项目常用功能详解

    2023-06-04 17:14:21
  • 25行Java代码将普通图片转换为字符画图片和文本的实现

    2023-11-24 02:04:26
  • ReentrantLock源码详解--公平锁、非公平锁

    2023-04-22 17:18:56
  • Java实现经典游戏Flappy Bird的示例代码

    2022-03-28 07:05:37
  • Android ContentProvider查看/读取手机联系人实例

    2021-10-13 07:10:13
  • Spring Boot教程之提高开发效率必备工具lombok

    2021-08-23 11:12:43
  • jcrop 网页截图工具(插件)开发

    2022-10-21 22:30:19
  • Spring配置shiro时自定义Realm中属性无法使用注解注入的解决办法

    2022-09-18 11:18:22
  • asp之家 软件编程 m.aspxhome.com