Hugo 日志 AOP AspectJ


Hugo是JakeWharton大神开发的一个通过注解触发的Debug日志库。它是一个非常好的AOP框架,在Debug模式下,Hugo利用aspectj库来进行切面编程,插入日志代码,用极小的代价帮我们实现优雅的函数监控

GitHub 简介

Annotation-triggered注解触发 method call方法调用 logging for your debug builds调试版本.

As a programmer, you often add log statements片段、语句 to print method calls, their arguments, their return values, and the time it took to execute

This is not a question. Every one of you does this. Shouldn't it be easier?

Simply add @DebugLog to your methods and you will automatically自动 get all of the things listed above logged for free.

@DebugLog
public String getName(String first, String last) {
  SystemClock.sleep(15); // Don't ever really do this!
  return first + " " + last;
}
5
5
 
1
@DebugLog
2
public String getName(String first, String last) {
3
  SystemClock.sleep(15); // Don't ever really do this!
4
  return first + " " + last;
5
}
V/Example: ⇢ getName(first="Jake", last="Wharton")
V/Example: ⇠ getName [16ms] = "Jake Wharton"
2
2
 
1
V/Example:  getName(first="Jake", last="Wharton")
2
V/Example:  getName [16ms] = "Jake Wharton"

The logging will only happen in debug builds and the annotation itself is never present存在于 in the compiled class file编译的类文件 for any build type. 

This means you can keep the annotation and check it into检入 source control源代码控制. It has zero effect on non-debug builds.


Add it to your project today!


Local Development

(不知道这几个步骤是搞什么玩意的)Working on this project? Here's some helpful Gradle tasks:

  • install - Install plugin, runtime, and annotations into local repo.
  • cleanExample - Clean the example project build.
  • assembleExample - Build the example project. Must run install first.
  • installExample - Build and install the example project debug APK onto a device.


使用步骤

1、在 project 的 build.gradle 中添加:
buildscript {
  repositories {
    mavenCentral()
  }

  dependencies {
    classpath 'com.jakewharton.hugo:hugo-plugin:1.2.1'
  }
}
9
9
 
1
buildscript {
2
  repositories {
3
    mavenCentral()
4
  }
5
 
          
6
  dependencies {
7
    classpath 'com.jakewharton.hugo:hugo-plugin:1.2.1'
8
  }
9
}

2、在module的 build.gradle 中添加:

apply plugin: 'com.jakewharton.hugo'
1
1
 
1
apply plugin: 'com.jakewharton.hugo'

3、(此配置应该是废弃了)Disable logging temporarily暂时 by adding the following:

hugo {
  enabled false
}
3
3
 
1
hugo {
2
  enabled false
3
}

(此配置应该是废弃了)If you want to toggle logging at runtime, use 

Hugo.setEnabled(true|false)
1
1
 
1
Hugo.setEnabled(true|false)

4、在需要的的类、方法、构造方法上加上注解即可

@DebugLog
1
1
 
1
@DebugLog


实现原理简介

Hugo可以用极小的代价帮我们实现优雅的函数监控。
Hugo虽然是一个比较小的项目,但是里面却包含了很多非常优秀的思想以及先进的技术:AOP、Aspect、注解、Gradle、gradle-maven等。
Hugo给我们提供了一种思路,即在Android中,也可以利用AOP的思路实现优雅的面向切面编程,例如用来统计打点等。

源码分析可参考: Hugo源码分析 和  Hugo探究

其实,从源码上来看,除了一个 Hugo 类外,这个库没有其他什么内容了。
795730-20180425191713829-1981154058.png
当然, 此库依赖了 org.aspectj.lang 包。
795730-20180425191714200-1546005515.png

一个注解 DebugLog:
@Target({TYPE, METHOD, CONSTRUCTOR})  //注意类是TYPE的一种)和方法,所以可以用在类上
@Retention(CLASS)  //保留策略为CLASS,即编译器将把注解记录在类文件中,因为不是RUNTIME,所以运行时注解丢掉了
//注意,如果我们需要在运行时获取注解信息(比如注解中有字段且需要在运行时获取到此字段的值),则Retention必须设为【RUNTIME】
public @interface DebugLog {
}
5
5
 
1
@Target({TYPE, METHOD, CONSTRUCTOR})  //注意类是TYPE的一种)和方法,所以可以用在类上
2
@Retention(CLASS)  //保留策略为CLASS,即编译器将把注解记录在类文件中,因为不是RUNTIME,所以运行时注解丢掉了
3
//注意,如果我们需要在运行时获取注解信息(比如注解中有字段且需要在运行时获取到此字段的值),则Retention必须设为【RUNTIME】
4
public @interface DebugLog {
5
}
Hugo.java 类,也就一百行代码,其中与我们业务相关的 核心代码为 logAndExecute(ProceedingJoinPoint):
@Around("method() || constructor()")
public Object logAndExecute(ProceedingJoinPoint joinPoint) throws Throwable {
	enterMethod(joinPoint);  //ProceedingJoinPoint有参数信息,输出参数的值

	long startNanos = System.nanoTime();//函数执行前记录时间,像我们手动做的一样
	Object result = joinPoint.proceed();//这里代表我们监控的函数
	long stopNanos = System.nanoTime();//函数执行结束时,打点记录时间,并计算耗时
	long lengthMillis = TimeUnit.NANOSECONDS.toMillis(stopNanos - startNanos);

	exitMethod(joinPoint, result, lengthMillis);//输出函数的值,执行耗时

	return result;
}
x
13
 
1
@Around("method() || constructor()")
2
public Object logAndExecute(ProceedingJoinPoint joinPoint) throws Throwable {
3
    enterMethod(joinPoint);  //ProceedingJoinPoint有参数信息,输出参数的值
4
 
          
5
    long startNanos = System.nanoTime();//函数执行前记录时间,像我们手动做的一样
6
    Object result = joinPoint.proceed();//这里代表我们监控的函数
7
    long stopNanos = System.nanoTime();//函数执行结束时,打点记录时间,并计算耗时
8
    long lengthMillis = TimeUnit.NANOSECONDS.toMillis(stopNanos - startNanos);
9
 
          
10
    exitMethod(joinPoint, result, lengthMillis);//输出函数的值,执行耗时
11
 
          
12
    return result;
13
}

PS:Hugo运行还离不开自己JakeWharton开发的一个编译器,值加上以上jar包或依赖,在Android框架下并不会执行。

2018-4-23





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值