AOP在Android中的使用(作为依赖库)

原创 2017年02月23日 15:04:51

上篇博客中无法对构造方法应用AOP,本篇做了修改


项目目录:



没有给出的类,在上篇博客中:

依赖库中的build.gradle文件

apply plugin: 'com.android.library'

import com.android.build.gradle.LibraryPlugin
import org.aspectj.bridge.IMessage
import org.aspectj.bridge.MessageHandler
import org.aspectj.tools.ajc.Main

buildscript {
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath 'org.aspectj:aspectjtools:1.8.9'
        classpath 'org.aspectj:aspectjweaver:1.8.9'
    }
}

android {
    compileSdkVersion 25
    buildToolsVersion "25.0.2"
    lintOptions {
        abortOnError false
    }

    defaultConfig {
        minSdkVersion 15
        targetSdkVersion 25
        versionCode 1
        versionName "1.0"

        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"

    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}


android.libraryVariants.all { variant ->
    LibraryPlugin plugin = project.plugins.getPlugin(LibraryPlugin)
    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", plugin.project.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;
            }
        }
    }
}

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
        exclude group: 'com.android.support', module: 'support-annotations'
    })
    compile 'com.android.support:appcompat-v7:25.1.0'
    testCompile 'junit:junit:4.12'
}




主工程build.gradle文件

apply plugin: 'com.android.application'

import org.aspectj.bridge.IMessage
import org.aspectj.bridge.MessageHandler
import org.aspectj.tools.ajc.Main
buildscript {
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath 'org.aspectj:aspectjtools:1.8.9'
        classpath 'org.aspectj:aspectjweaver:1.8.9'
    }
}
android {
    compileSdkVersion 25
    buildToolsVersion "25.0.2"
    defaultConfig {
        applicationId "cn.edu.sxu.www.aopdemolibrary"
        minSdkVersion 15
        targetSdkVersion 25
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

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.8",
                         "-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;
            }
        }
    }
}

dependencies {
    compile fileTree(include: ['*.jar'], dir: 'libs')
    androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
        exclude group: 'com.android.support', module: 'support-annotations'
    })
    compile 'com.android.support:appcompat-v7:25.1.0'
    testCompile 'junit:junit:4.12'
    compile project(':aoplibrary')
}



TraceAspect.java类做了修改,增加了对构造函数的支持

package cn.edu.sxu.www.aoplibrary;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.CodeSignature;
import org.aspectj.lang.reflect.ConstructorSignature;
import org.aspectj.lang.reflect.MethodSignature;

/**
 * Aspect representing the cross cutting-concern: Method and Constructor Tracing.
 */
@Aspect
public class TraceAspect {

  private static final String POINTCUT_METHOD =
      "execution(@cn.edu.sxu.www.aoplibrary.DebugTrace * *(..))";

  private static final String POINTCUT_CONSTRUCTOR =
      "execution(@cn.edu.sxu.www.aoplibrary.DebugTrace *.new(..))";

  @Pointcut(POINTCUT_METHOD)
  public void methodAnnotatedWithDebugTrace() {}

  @Pointcut(POINTCUT_CONSTRUCTOR)
  public void constructorAnnotatedDebugTrace() {}

  @Around("methodAnnotatedWithDebugTrace() || constructorAnnotatedDebugTrace()")
  public Object weaveJoinPoint(ProceedingJoinPoint joinPoint) throws Throwable {

    CodeSignature methodSignature=null;
    if(joinPoint.getSignature() instanceof  MethodSignature)//普通方法
    {
      methodSignature = (MethodSignature) joinPoint.getSignature();
    }
    else if(joinPoint.getSignature() instanceof  ConstructorSignature)//构造方法
    {
      methodSignature = (ConstructorSignature) 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()));

    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("Gintonic --> ");
    message.append(methodName);
    message.append(" --> ");
    message.append("[");
    message.append(methodDuration);
    message.append("ms");
    message.append("]");

    return message.toString();
  }
}


MainActivity.java类

package cn.edu.sxu.www.aopdemolibrary;

import android.os.Bundle;
import android.os.SystemClock;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;

import cn.edu.sxu.www.aoplibrary.DebugLog;
import cn.edu.sxu.www.aoplibrary.DebugTrace;
import cn.edu.sxu.www.aoplibrary.StopWatch;

public class MainActivity extends AppCompatActivity implements View.OnClickListener{

    private Button button;
    private Button button2;
    private Button button3;
    private String TAG="cn.edu.sxu.www.aopdemo.MainActivity";
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        button= (Button) findViewById(R.id.button);
        button2= (Button) findViewById(R.id.button2);
        button3= (Button) findViewById(R.id.button3);
        button.setOnClickListener(this);
        button2.setOnClickListener(this);
        button3.setOnClickListener(this);
    }

    @Override
    public void onClick(View view) {

        switch (view.getId())
        {
            case R.id.button:
                commonTest();
                break;
            case R.id.button2:
                aopTest();
                break;
            case R.id.button3:
                initConstructor();
                break;
        }

    }

    /**
     * 普通统计
     */

    private void  commonTest()
    {
        final StopWatch stopWatch = new StopWatch();
        stopWatch.start();
        SystemClock.sleep(2000);
        stopWatch.stop();

        DebugLog.log(TAG, "所用时长:"+stopWatch.getTotalTimeMillis());

    }

    /**
     * aop 统计
     */
    @DebugTrace
    private void aopTest()
    {
        SystemClock.sleep(3000);
    }

    /**
     * 演示构造方法
     */
    private void initConstructor()
    {

//        Person person=new Person("张三",10);
//        person.setAge(80);
        Person person=new Person();
    }
}



activity_main.xml文件

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    >

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="官网demo,统计方法运行时间"
        android:id="@+id/textView" />

    <Button
        android:text="普通方式"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/textView"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true"
        android:layout_marginTop="42dp"
        android:id="@+id/button" />

    <Button
        android:text="aop方式"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/button"
        android:layout_alignRight="@+id/button"
        android:layout_alignEnd="@+id/button"
        android:layout_marginTop="87dp"
        android:id="@+id/button2" />

    <Button
        android:text="aop构造方法"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginBottom="69dp"
        android:id="@+id/button3"
        android:layout_alignParentBottom="true"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true" />
</RelativeLayout>


Person.java类

package cn.edu.sxu.www.aopdemolibrary;

import android.os.SystemClock;

import java.io.Serializable;

import cn.edu.sxu.www.aoplibrary.DebugTrace;

/**
 * Created by ${huozhenpeng} on 17/2/23.
 * Company : www.miduo.com
 * 演示AOP对构造方法的使用
 */

public class Person implements Serializable {


    private String name;
    private int age;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    @DebugTrace
    public void setAge(int age) {
        this.age = age;
        SystemClock.sleep(100);
    }

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
        SystemClock.sleep(1000);
    }
    @DebugTrace
    public Person() {

        SystemClock.sleep(1500);
    }
}



源码地址:http://download.csdn.net/detail/huohacker/9761903

Android进阶系列之AOP面向切面编程

Android的博大精深,不是一言两语能够说明道清的,它的魅力只有亲身去接触才能体会。就像美女一样 我先在这里申明一下,我这篇AOP只是学习笔记,适合入门级选手,如果阁下是大神想要参考AOP,那么...
  • sw5131899
  • sw5131899
  • 2016-12-26 17:30:34
  • 6569

Android 开发中使用 AOP

大家对AOP应该都不陌生, 就算没有用过也肯定听说过. 用过或了解过Java AOP的同学应该都知道AspectJ的大名. 因为AspectJ与java程序完全兼容,几乎是无缝关联, 所以只需要做一些...
  • l2show
  • l2show
  • 2017-03-19 14:19:44
  • 2261

深入理解Android之AOP

深入理解Android之AOP格式更加精美的PDF版请到:http://vdisk.weibo.com/s/z68f8l0xTgCLK 下载一、闲谈AOP大家都知道OOP,即ObjectOriente...
  • Innost
  • Innost
  • 2015-10-24 19:48:31
  • 51849

Android中的AOP编程之AspectJ实战实现数据埋点

文章背景 最近在给某某银行做项目的时,涉及到了数据埋点,性能监控等问题,那我们起先想到的有两种方案,方案之一就是借助第三方,比如友盟、Bugly等,由于项目是部署在银行的网络框架之内的,所以该方案不可...
  • XiNanHeiShao
  • XiNanHeiShao
  • 2017-07-01 22:55:06
  • 3397

AOP在Android中最佳用法

AOP AOP(Aspect Oriented Programming)是面向切面编程,AOP和我们平时接触的OOP编程是不同的编程思想,OOP是面向对象编程,提倡的是将功能模块化,对象化。而AOP...
  • a296777513
  • a296777513
  • 2018-02-28 16:58:51
  • 160

Android AOP 总结

AndroidAOP 总结 一、AOP 1.1 什么是AOP AOP,AspectOriented Programming 面向切面编程 OOP,Object-orientedprogramming面...
  • chenzhiqin20
  • chenzhiqin20
  • 2017-03-16 21:24:45
  • 904

Android中的AOP编程

Android 中的 AOP 编程 原文链接 : Aspect Oriented Programming in Android原文作者 : Fernando Cejas译文出自 : 开发...
  • chen03050903
  • chen03050903
  • 2016-06-13 15:25:10
  • 464

使用AspectJ在Android中实现Aop

开题上一篇文章Android Aop预研中介绍了Aop的各种实现方式,并且在最后提到,选择AspectJ作为合适的开发方式。这篇文章通过我自己编写的一个例子,来说明AspectJ的使用。首先要声明,使...
  • kangaroo835127729
  • kangaroo835127729
  • 2016-07-24 16:36:45
  • 11491

Android基于AOP的非侵入式监控之——AspectJ实战

本博文的目的不是详细的介绍AspectJ的细节,而是最近项目用到了AspectJ,因此对其作了一些使用和重要概念上的总结。 相信很多做过Web的同学对[AspectJ](https://eclipse...
  • woshimalingyi
  • woshimalingyi
  • 2016-05-24 10:45:15
  • 13834

Android中的AOP编程

面向切面编程(AOP,Aspect-oriented programming)需要把程序逻辑分解成『关注点』(concerns,功能的内聚区域)。这意味着,在 AOP 中,我们不需要显式的修改就可以向...
  • u013378580
  • u013378580
  • 2016-08-11 20:54:33
  • 1531
收藏助手
不良信息举报
您举报文章:AOP在Android中的使用(作为依赖库)
举报原因:
原因补充:

(最多只允许输入30个字)