前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >AspectJ在android上的开发

AspectJ在android上的开发

作者头像
包子388321
发布2020-06-16 18:33:38
1.3K0
发布2020-06-16 18:33:38
举报
文章被收录于专栏:包子的书架包子的书架

Android上运用AOP的思想开发,可以快速的帮助我们简化在横向开发中的重复性工作,简单的说就是把涉及到众多模块的某一类问题进行统一管理比如:性能检测、日志打印手机等。 AspectJ实际上是对AOP编程思想的一个实践,当然,除了AspectJ以外,还有很多其它的AOP实现,例如ASMDex、javassist等,但目前最好、最方便的,依然是AspectJ。

直接贴例子
  • 引入插件,这边是添加在app.gradle, 不是添加在项目的gradle中
代码语言:javascript
复制
import org.aspectj.bridge.IMessage
import org.aspectj.bridge.MessageHandler
import org.aspectj.tools.ajc.Main

buildscript {
  repositories {
    mavenCentral()
  }
  dependencies {
    classpath 'org.aspectj:aspectjtools:1.8.1'   //引入aspectj的classpath
  }
}

apply plugin: 'com.android.application'

android {
  compileSdkVersion 26
  buildToolsVersion "26.0.2"
  defaultConfig {
    applicationId "m4399.aspectjdemo"
    minSdkVersion 19
    targetSdkVersion 26
    versionCode 1
    versionName "1.0"
    testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
  }
  buildTypes {
    release {
      minifyEnabled false
      proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
    }
  }
}

dependencies {
  compile fileTree(dir: 'libs', include: ['*.jar'])
  compile 'com.android.support:appcompat-v7:26.+'
  compile 'com.android.support.constraint:constraint-layout:1.0.2'
  testCompile 'junit:junit:4.12'
  compile 'org.aspectj:aspectjrt:1.8.1'   //添加对应的依赖
}


final def log = project.logger
final def variants = project.android.applicationVariants
//在全局变量中配置编译项以及,对应的log输出
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;
      }
    }
  }
}
  • 编写注解
代码语言:javascript
复制
@Retention(RetentionPolicy.CLASS)
@Target({ ElementType.CONSTRUCTOR, ElementType.METHOD })
public @interface DebugTrace {
}
  • 日志打印类
代码语言:javascript
复制
public class DebugLog {
  private DebugLog() {}

  /**
   * Send a debug log message
   *
   * @param tag Source of a log message.
   * @param message The message you would like logged.
   */
  public static void log(String tag, String message) {
    Log.d(tag, message);
  }
}
  • 方法耗时检测类
代码语言:javascript
复制
public class StopWatch {

  private long startTime;
  private long endTime;
  private long elapsedTime;

  public StopWatch() {
    //empty
  }

  private void reset() {
    startTime = 0;
    endTime = 0;
    elapsedTime = 0;
  }

  public void start() {
    reset();
    startTime = System.nanoTime();
  }

  public void stop() {
    if (startTime != 0) {
      endTime = System.nanoTime();
      elapsedTime = endTime - startTime;
    } else {
      reset();
    }
  }

  public long getTotalTimeMillis() {
    return (elapsedTime != 0) ? TimeUnit.NANOSECONDS.toMillis(endTime - startTime) : 0;
  }
}
  • Aspect 类的开发
代码语言:javascript
复制
@Aspect
public class TraceAspect {

  private static final String POINTCUT_METHOD =
      "execution(@com.bao.aspectjdemo.DebugTrace * *(..))";  //对应着注解类的包名+类名

  private static final String POINTCUT_CONSTRUCTOR =
      "execution(@com.bao.aspectjdemo.DebugTrace *.new(..))";

  @Pointcut(POINTCUT_METHOD)
  public void methodAnnotatedWithDebugTrace() {}

  @Pointcut(POINTCUT_CONSTRUCTOR)
  public void constructorAnnotatedDebugTrace() {}

  @Around("methodAnnotatedWithDebugTrace() || constructorAnnotatedDebugTrace()")
  public Object weaveJoinPoint(ProceedingJoinPoint joinPoint) throws Throwable {
    MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
    String className = methodSignature.getDeclaringType().getSimpleName();
    String methodName = methodSignature.getName();

    final StopWatch stopWatch = new StopWatch();
    stopWatch.start();
    Object result = joinPoint.proceed();
    stopWatch.stop();

    DebugLog.log(className, buildLogMessage(methodName, stopWatch.getTotalTimeMillis()));

    return result;
  }

  /**
   * Create a log message.
   *
   * @param methodName A string with the method name.
   * @param methodDuration Duration of the method in milliseconds.
   * @return A string representing message.
   */
  private static String buildLogMessage(String methodName, long methodDuration) {
    StringBuilder message = new StringBuilder();
    message.append("AspectJDemo --> ");
    message.append(methodName);
    message.append(" --> ");
    message.append("[");
    message.append(methodDuration);
    message.append("ms");
    message.append("]");

    return message.toString();
  }
}
  • 调用
代码语言:javascript
复制
  @DebugTrace
  @Override
  public void onClick(View v) {
    try {
      Thread.sleep(10);
    } catch (InterruptedException e) {
      e.printStackTrace();
    }
  }

以上是个人参考例子https://github.com/android10/Android-AOPExample 熟悉了一遍 补充:Android-AOPExample的例子下载下来,在gradle版本再2.3.0及其以上的版本编译会出现问题 报错误:No such property: project for class: com.android.build.gradle.LibraryPlugin

  • 解决方法一:注释掉LibraryPlugin plugin = project.plugins.getPlugin(LibraryPlugin) 和 "-bootclasspath", plugin.project.android.bootClasspath.join(File.pathSeparator)
  • 解决方法二:将plugin.project.android.bootClasspath.join(File.pathSeparator) 替换为 android.bootClasspath.join(File.pathSeparator)

参考文章:

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 直接贴例子
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档