OOP(Object Oriented Programming):面向对象编程。把问题或功能模块化,每个模块处理自己的事。
AOP(Aspect Oriented Programming):面向切面编程。把分散于不同模块中的相同业务放到统一的地方来管理。如:日志记录,业务埋点,持久化,性能监控,数据校验,缓存,权限检查,异常处理等。
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:用来个一个类型声明额外的方法或属性
给方法添加性能测试
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.日志输出
由于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.日志输出