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

扫描二维码关注公众号,回复: 66302 查看本文章

(不知道这几个步骤是搞什么玩意的)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 类外,这个库没有其他什么内容了。

当然, 此库依赖了 org.aspectj.lang 包。

一个注解 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





猜你喜欢

转载自www.cnblogs.com/baiqiantao/p/0428214a9585ad26a32762dedbd57b53.html
今日推荐