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.日志输出

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.日志输出

cotlin java go_Aspectj 在Android中的简单使用(Java + Kotlin)-Go语言中文社区相关推荐

  1. rust的矿坑_转: Rust中的Pin详解 【Rust语言中文社区】

    Rust中的Pin详解 原创 automanyang Rust语言中文社区 昨天 https://mp.weixin.qq.com/s/PjctbPbyR5OeaqTHZdB5uQ 相关概念 Pin ...

  2. android studio添加繁体,Android (Android studio3.0.1)一篇可以实现app多语言的转换(简单操作)的教程-Go语言中文社区...

    最近接触到了项目需要,多语言的转换.网上有很多资料,我整理一些,简单适合自己使用的操作. 第一步:打开Android studio 添加 Android Studio插件:AndroidLocaliz ...

  3. java 航班_Java实现简单航班查询系统-Go语言中文社区

    #java实现简单航班管理系统 题目要求:声明一个Flight(航班)类,该类包含private域航班号(如:CA1430),起飞时间(如:10:15AM),到达时间(如:2:30PM).为该类声明合 ...

  4. java黄金连分数_蓝桥杯 | Java B组省赛真题练习——黄金连分数-Go语言中文社区...

    标题: 黄金连分数 黄金分割数0.61803... 是个无理数,这个常数十分重要,在许多工程问题中会出现.有时需要把这个数字求得很精确. 对于某些 精密工程,常数的精度很重要.也许你听说过哈勃太空望远 ...

  5. linux apk 拆分 odex,android apk反编译和odex转dex-Go语言中文社区

    http://www.cnblogs.com/wanqieddy/archive/2012/03/01/2375424.html 大家好,这里介绍apk反编译操作. 1:apk反编译 2:odex转d ...

  6. android 开发tv盒子,一步一步学习Android TV/盒子开发(二)-Go语言中文社区

    TV.机顶盒开发调试不能像手机一样通过USB线连接调试,可通过ADB连接调试 连接电视 adb connect 10.74.84.199 连接后就可以开始开发调试了! 断开连接 // 断开某个设备 a ...

  7. 基于python爬虫的论文标题_python爬虫——简单论文标题检索-Go语言中文社区

    有趣的爬虫,独有的意义召唤着我去学习,去尝试.最近有感于每天对于论文的收集,感觉自己的收集速度赶不上论文的更新速度,同时对于自己想找到的论文的收集比较麻烦.因此,学习用python写一个很简单的爬虫, ...

  8. java以太坊源码分析_以太坊区块链Java(EthereumJ)学习笔记:区块链结构-Go语言中文社区...

    本文对EthereumJ的区块链相关的代码做一个简单的介绍. 以太坊区块链 以太坊区块链是在Bitcoin区块链的基础上发展起来的.区块链的数据结构既保留了Bitcoin区块链验证数据的真实性和完整性 ...

  9. node如何输出html页面,【自己的整理】node.js直接输出一个非常简单的HTML页面-Go语言中文社区...

    刚开始接触nodejs,先记录一下最开始用node输出一个很简单的界面 在远程服务器上先创建一个js文件 helloworld.js [root@towrabbit nodejsLearn]# vi ...

最新文章

  1. ”计算机操作系统“学习笔记1
  2. 利用GNU的parted进行分区
  3. 世界32条谣言,你被骗了多少?
  4. 数据库连接python_python连接数据库
  5. 解决canvas画图模糊的问题
  6. c#事务的使用、示例及注意事项
  7. x230无线网卡驱动服务器版,ThinkPad X230网卡驱动
  8. android layout 渲染,java – 渲染android.support.design.widget.CoordinatorLayout的问题
  9. 基于matlab的瑞利衰落信道建模和仿真
  10. python快速搭建服务器方法
  11. 2019寒假专题一 L CodeForces - 1260B
  12. 谷歌浏览器配置微信浏览器_在 Chrome (谷歌浏览器) 中模拟微信内置浏览器
  13. html5以图片为背景的代码,HTML5画布背景图片
  14. 最小公倍数C语言怎么算,算法:最大公约数和最小公倍数(C语言表示)
  15. ‘Converting circular structure to JSON‘报错的解决方案
  16. 电子科技大学硕士毕业论文和博士毕业论文Latex模板及问题集锦
  17. Python 数据分析微专业课程--项目06 城市餐饮店铺选址分析
  18. 数智化时代,驱动企业转型升级的“三驾马车”是什么?
  19. 流媒体服务器——Licode Janus-gateway Mediasoup Medooze 分析
  20. java模拟回合制游戏大小姐_[源码和文档分享]基于java的RPG回合制游戏

热门文章

  1. mui框架 页面无法滚动解决方法
  2. clickhouse 复杂查询时嵌套连接join可能存在的异常解决(xjl456852原创)
  3. System.UriFormatException: Invalid URI 解决方法
  4. mysql运维技巧_​mysql初级运维使用技巧
  5. TikTok如何将粉丝转到私域,提高转化和复购?
  6. 跨境电商和独立站哪个好?
  7. Google浏览器一开启就提示“请停用以开发者模式运行的扩展程序“解决方案
  8. Leetcode每日一题:345.reverse-vowels-of-a-string(反转字符串中的元音字母)
  9. Leetcode:8.string-to-integer-atoi(字符串转整数)
  10. 对文件夹内所有文件批量命名