AspectJ

AspectJ实际上是对AOP编程思想的一个实践,当然,除了AspectJ以外,还有很多其它的AOP实现,例如ASMDex,但目前最好、最方便的,依然是AspectJ。

AOP的用处非常广,从Spring到Android,各个地方都有使用,特别是在后端,Spring中已经使用的非常方便了,而且功能非常强大,但是在Android中,AspectJ的实现是略阉割的版本,并不是所有功能都支持,但对于一般的客户端开发来说,已经完全足够用了。

在Android上集成AspectJ实际上是比较复杂的,不是一句话就能compile,但是,鄙司已经给大家把这个问题解决了,大家现在直接使用这个SDK就可以很方便的在Android Studio中使用AspectJ了。Github地址如下:

https://github.com/HujiangTechnology/gradle_plugin_android_aspectjx

另外一个比较成功的使用AOP的库是Jake大神的Hugo:

https://github.com/JakeWharton/hugo

AOP 能做什么?

持久化
性能监控
数据校验
缓存

1.引入 AspectJ

app/build.grade加入以下配置项,app和library配置相同:

import org.aspectj.bridge.IMessageimport org.aspectj.bridge.MessageHandlerimport org.aspectj.tools.ajc.Mainapply plugin: 'com.android.library'android {    compileSdkVersion 26    defaultConfig {        minSdkVersion 15        targetSdkVersion 26        versionCode 1        versionName "1.0"        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"    }    buildTypes {        release {            minifyEnabled false            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'        }    }}repositories {    jcenter()    mavenCentral()}buildscript {    repositories {        jcenter()        mavenCentral()    }    dependencies {        classpath 'org.aspectj:aspectjtools:1.8.9'        // 如果是android library 要加上        classpath 'org.aspectj:aspectjweaver:1.8.9'    }}dependencies {    compile fileTree(dir: 'libs', include: ['*.jar'])    compile 'org.aspectj:aspectjrt:1.8.9'//    compile 'com.android.support:appcompat-v7:27.1.1'}android.libraryVariants.all { variant ->    JavaCompile javaCompile = variant.javaCompile    javaCompile.doLast {        String[] args = ["-showWeaveInfo",                         "-1.8",                         "-inpath", javaCompile.destinationDir.toString(),                         "-aspectpath", javaCompile.classpath.asPath,                         "-d", javaCompile.destinationDir.toString(),                         "-classpath", javaCompile.classpath.asPath,                         "-bootclasspath", android.bootClasspath.join(                File.pathSeparator)]        MessageHandler handler = new MessageHandler(true)        new Main().run(args, handler)        def log = project.logger        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:                case IMessage.INFO:                    log.info message.message, message.thrown                    break                case IMessage.DEBUG:                    log.debug message.message, message.thrown                    break            }        }    }}

2.AspectJ 语法

JPoint:代码可注入的点,比如一个方法的调用处或者方法内部、“读、写”变量等。
Pointcut:用来描述 JPoint 注入点的一段表达式,比如:调用 Animal 类 fly 方法的地方,call(* Animal.fly(..))。
Advice:常见的有 Before、After、Around 等,表示代码执行前、执行后、替换目标代码,也就是在 Pointcut 何处注入代码。
Aspect:Pointcut 和 Advice 合在一起称作 Aspect。

Android AOP(二):AspectJ在Android中实现Aop_第1张图片

Android AOP(二):AspectJ在Android中实现Aop_第2张图片

Android AOP(二):AspectJ在Android中实现Aop_第3张图片

Android AOP(二):AspectJ在Android中实现Aop_第4张图片

3.使用

统计一下某个方法的运行时间

public class StopWatch {    private long startTime;    private long endTime;    private long elapsedTime;    public StopWatch() {        //empty    }    private void reset() {        startTime = 0;        endTime = 0;        elapsedTime = 0;    }    public void start() {        reset();        startTime = System.nanoTime();    }    public void stop() {        if (startTime != 0) {            endTime = System.nanoTime();            elapsedTime = endTime - startTime;        } else {            reset();        }    }    public long getTotalTimeMillis() {        return (elapsedTime != 0) ? TimeUnit.NANOSECONDS.toMillis(endTime - startTime) : 0;    }}
public class DebugLog {    private DebugLog() {}    /**     * Send a debug log message     *     * @param tag Source of a log message.     * @param message The message you would like logged.     */    public static void log(String tag, String message) {//        Log.i(tag, message);        System.out.print(message);    }}
@Retention(RetentionPolicy.CLASS)@Target({ ElementType.CONSTRUCTOR, ElementType.METHOD })public @interface DebugTrace {}
@Aspectpublic class TraceAspect {    private static final String POINTCUT_METHOD =            "execution(@com.example.libraryaspectj.DebugTrace * *(..))";    private static final String POINTCUT_CONSTRUCTOR =            "execution(@com.example.libraryaspectj.DebugTrace *.new(..))";    @Pointcut(POINTCUT_METHOD)    public void methodAnnotatedWithDebugTrace() {}    @Pointcut(POINTCUT_CONSTRUCTOR)    public void constructorAnnotatedDebugTrace() {}    @Around("methodAnnotatedWithDebugTrace() || constructorAnnotatedDebugTrace()")    public Object weaveJoinPoint(ProceedingJoinPoint joinPoint) throws Throwable {        MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();        String className = methodSignature.getDeclaringType().getSimpleName();        String methodName = methodSignature.getName();        final StopWatch stopWatch = new StopWatch();        stopWatch.start();        Object result = joinPoint.proceed();        stopWatch.stop();        DebugLog.log(className, buildLogMessage(methodName, stopWatch.getTotalTimeMillis()));        Log.i("*** yang",buildLogMessage(methodName, stopWatch.getTotalTimeMillis()));        return result;    }    /**     * Create a log message.     *     * @param methodName A string with the method name.     * @param methodDuration Duration of the method in milliseconds.     * @return A string representing message.     */    private static String buildLogMessage(String methodName, long methodDuration) {        StringBuilder message = new StringBuilder();        message.append("methodName --> ");        message.append(methodName);        message.append(" --> ");        message.append("[");        message.append(methodDuration);        message.append("ms");        message.append("]");        return message.toString();    }}

然后在app中的某activity

...    @DebugTrace    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_file_list);...

即会打印出 I/* yang: Libraryaspectj –> onCreate –> [82ms]

以上就是对aspectj的简单实现后续展开都是遵循aspectj语法的使用

aspecjt文档

更多相关文章

  1. Android MP4取得播放时长的方法
  2. Android中执行java命令的方法及java代码执行并解析shell命令
  3. Android 导入项目时报Android.jar包丢失解决方法
  4. 干货 | 聊聊这些年总结的一些学习方法
  5. Android手机访问Django测试服务器方法
  6. android Map 使用方法
  7. Android学习日记----------Android 10调用摄像头闪退问题---《第
  8. Android实现屏幕旋转方法总结

随机推荐

  1. Android RecyclerView 间距全适配
  2. Android SetTextColor
  3. Android学习笔记(十九)
  4. Android SSO 相关文章
  5. 封装Android OKHttp3.0请求工具
  6. android 7.0 使用apktool反编译apk
  7. 基于Android的短信管理系统
  8. Android 1.5 自带的图标一览表
  9. Android ContextMenu上下文菜单
  10. Android那些“没用“知识(一)