热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

cotlinjavago_Aspectj在Android中的简单使用(Java+Kotlin)Go语言中文社区

OOP&AOPOOP(ObjectOrientedProgramming):面向对象编程。把问题或功能模块化,每个模块处理自己的事。AOP(AspectOriente

OOP&AOP

OOP(Object Oriented Programming):面向对象编程。把问题或功能模块化,每个模块处理自己的事。

AOP(Aspect Oriented Programming):面向切面编程。把分散于不同模块中的相同业务放到统一的地方来管理。如:日志记录,业务埋点,持久化,性能监控,数据校验,缓存,权限检查,异常处理等。

AspectJ简介

AspectJ定义了AOP语法,所以它有一个专门的编译器用来生成遵守Java字节编码规范的Class文件,在编译期注入代码。代表框架:Hugo(Jake Wharton)

基本概念

Join Points:连接点,程序中可切入的点。如:方法调用时,读取某个变量时

Pointcut:切入点,代码注入的位置,其实就是有条件限定的Join Point,例如只在特定方法中注入代码

Aspect:切面,一个关注点的模块化

Advice:在切入点注入的代码,一般有before、after、around三种类型

Target Object:被一个或多个aspect横切拦截操作的目标对象

Weaving:把Advice代码织入到目标对象的过程

Inter-type declarations:用来个一个类型声明额外的方法或属性

Demo示例

给方法添加性能测试

Java版本

1.添加依赖

Project->bulid.gradle

dependencies {

...

classpath 'org.aspectj:aspectjtools:1.8.13'

classpath 'org.aspectj:aspectjweaver:1.8.13'

}

Module->build.gradle

dependencies {

...

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.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

}

}

}

}

2.自定义注解

@Target(ElementType.METHOD)

@Retention(RetentionPolicy.RUNTIME)

public @interface PerformanceAnnotation {

String value();

}

3.自定义切面

@Aspect

public class PerformanceAspect {

public static final String TAG = PerformanceAspect.class.getSimpleName();

@Pointcut("execution(@ com.tongjin.aspectj.java.PerformanceAnnotation * *(..))")

public void performancePointcut(){}

@Around("performancePointcut()")

public Object wavePerformancePointcut(ProceedingJoinPoint joinPoint) throws Throwable {

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

// 类名

String className = methodSignature.getDeclaringType().getSimpleName();

// 方法名

String methodName = methodSignature.getName();

// 功能名

PerformanceAnnotation behaviorTrace = methodSignature.getMethod().getAnnotation(PerformanceAnnotation.class);

String value = behaviorTrace.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));

return result;

}

}

4.使用

@PerformanceAnnotation("performance")

public void clickMe(View view) {

Toast.makeText(this, "Click", Toast.LENGTH_SHORT).show();

}

5.日志输出

c95bb60e7c2df5cd30c70d3a78a309eb.png

Kotlin版本

由于java版本添加依赖的方式,在kotlin中不起作用,采用大神方案

1.添加依赖

Project->build.gradle

dependencies {

...

classpath 'com.hujiang.aspectjx:gradle-android-plugin-aspectjx:2.0.4'

}

Module->bulid.gradle

apply plugin: 'android-aspectjx'

2.自定义注解

@Target(AnnotationTarget.FUNCTION)

@Retention(AnnotationRetention.RUNTIME)

annotation class PerformanceAnnotation(val value: String)

3.自定义切面

@Aspect

class PerformanceAspect {

companion object {

val TAG = PerformanceAspect::class.java.simpleName

}

@Pointcut("execution(@ com.tongjin.myapplication.PerformanceAnnotation * *(..))")

fun performancePointcut() {

}

@Around("performancePointcut()")

@Throws(Throwable::class)

fun wavePerformancePointcut(joinPoint: ProceedingJoinPoint) {

val methodSignature = joinPoint.signature as MethodSignature

// 类名

val className = methodSignature.declaringType.simpleName

// 方法名

val methodName = methodSignature.name

// 功能名

val behaviorTrace = methodSignature.method.getAnnotation(PerformanceAnnotation::class.java)

val value = behaviorTrace.value

val start = System.currentTimeMillis()

joinPoint.proceed()

val duration = System.currentTimeMillis() - start

Log.e(TAG, "${className}类中${methodName}方法执行${value}功能,耗时:${duration}ms")

}

}

4.使用

@PerformanceAnnotation("performance")

fun clickMe(view: View) {

Toast.makeText(this, "Click", Toast.LENGTH_SHORT).show()

}

5.日志输出

d93c1500f51f92502794d1f0bbb747c8.png



推荐阅读
  • 开发笔记:加密&json&StringIO模块&BytesIO模块
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了加密&json&StringIO模块&BytesIO模块相关的知识,希望对你有一定的参考价值。一、加密加密 ... [详细]
  • Android自定义控件绘图篇之Paint函数大汇总
    本文介绍了Android自定义控件绘图篇中的Paint函数大汇总,包括重置画笔、设置颜色、设置透明度、设置样式、设置宽度、设置抗锯齿等功能。通过学习这些函数,可以更好地掌握Paint的用法。 ... [详细]
  • Spring源码解密之默认标签的解析方式分析
    本文分析了Spring源码解密中默认标签的解析方式。通过对命名空间的判断,区分默认命名空间和自定义命名空间,并采用不同的解析方式。其中,bean标签的解析最为复杂和重要。 ... [详细]
  • 向QTextEdit拖放文件的方法及实现步骤
    本文介绍了在使用QTextEdit时如何实现拖放文件的功能,包括相关的方法和实现步骤。通过重写dragEnterEvent和dropEvent函数,并结合QMimeData和QUrl等类,可以轻松实现向QTextEdit拖放文件的功能。详细的代码实现和说明可以参考本文提供的示例代码。 ... [详细]
  • 使用Ubuntu中的Python获取浏览器历史记录原文: ... [详细]
  • MyBatis多表查询与动态SQL使用
    本文介绍了MyBatis多表查询与动态SQL的使用方法,包括一对一查询和一对多查询。同时还介绍了动态SQL的使用,包括if标签、trim标签、where标签、set标签和foreach标签的用法。文章还提供了相关的配置信息和示例代码。 ... [详细]
  • Java中包装类的设计原因以及操作方法
    本文主要介绍了Java中设计包装类的原因以及操作方法。在Java中,除了对象类型,还有八大基本类型,为了将基本类型转换成对象,Java引入了包装类。文章通过介绍包装类的定义和实现,解答了为什么需要包装类的问题,并提供了简单易用的操作方法。通过本文的学习,读者可以更好地理解和应用Java中的包装类。 ... [详细]
  • Iamtryingtomakeaclassthatwillreadatextfileofnamesintoanarray,thenreturnthatarra ... [详细]
  • 本文讨论了在Windows 8上安装gvim中插件时出现的错误加载问题。作者将EasyMotion插件放在了正确的位置,但加载时却出现了错误。作者提供了下载链接和之前放置插件的位置,并列出了出现的错误信息。 ... [详细]
  • Android Studio Bumblebee | 2021.1.1(大黄蜂版本使用介绍)
    本文介绍了Android Studio Bumblebee | 2021.1.1(大黄蜂版本)的使用方法和相关知识,包括Gradle的介绍、设备管理器的配置、无线调试、新版本问题等内容。同时还提供了更新版本的下载地址和启动页面截图。 ... [详细]
  • 图解redis的持久化存储机制RDB和AOF的原理和优缺点
    本文通过图解的方式介绍了redis的持久化存储机制RDB和AOF的原理和优缺点。RDB是将redis内存中的数据保存为快照文件,恢复速度较快但不支持拉链式快照。AOF是将操作日志保存到磁盘,实时存储数据但恢复速度较慢。文章详细分析了两种机制的优缺点,帮助读者更好地理解redis的持久化存储策略。 ... [详细]
  • 计算机存储系统的层次结构及其优势
    本文介绍了计算机存储系统的层次结构,包括高速缓存、主存储器和辅助存储器三个层次。通过分层存储数据可以提高程序的执行效率。计算机存储系统的层次结构将各种不同存储容量、存取速度和价格的存储器有机组合成整体,形成可寻址存储空间比主存储器空间大得多的存储整体。由于辅助存储器容量大、价格低,使得整体存储系统的平均价格降低。同时,高速缓存的存取速度可以和CPU的工作速度相匹配,进一步提高程序执行效率。 ... [详细]
  • 在重复造轮子的情况下用ProxyServlet反向代理来减少工作量
    像不少公司内部不同团队都会自己研发自己工具产品,当各个产品逐渐成熟,到达了一定的发展瓶颈,同时每个产品都有着自己的入口,用户 ... [详细]
  • 本文介绍了操作系统的定义和功能,包括操作系统的本质、用户界面以及系统调用的分类。同时还介绍了进程和线程的区别,包括进程和线程的定义和作用。 ... [详细]
  • Todayatworksomeonetriedtoconvincemethat:今天在工作中有人试图说服我:{$obj->getTableInfo()}isfine ... [详细]
author-avatar
2233
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有