AOP框架AspectJ的使用(Android)

Table of Contents

 

 

AOP框架AspectJ的使用(Android)

一、什么是AOP

二、AspectJ

三、在Android项目中使用AspectJ

3.1 配置AspectJ

3.2 自定义注解

3.3 用@Aspect标注切面

3.4 在切面类中定义PointCut(切入点)

3.5 在切面类中定义Advance(通知)

3.6 对方法使用该注解

3.6.1 对click方法标注

3.6.2 内部类方法的标注

3.6.3 对同一个方法多个按钮处理的标注

四、处理结果

五、项目结构

六、注入后生成的代码


 

AOP框架AspectJ的使用(Android)

一、什么是AOP

AOP是Aspect Oriented Programming的缩写,即『面向切面编程』。它和我们平时接触到的OOP都是编程的不同思想,OOP,即『面向对象编程』,它提倡的是将功能模块化,对象化,而AOP的思想,则不太一样,它提倡的是针对同一类问题的统一处理,当然,我们在实际编程过程中,不可能单纯的安装AOP或者OOP的思想来编程,很多时候,可能会混合多种编程思想,大家也不必要纠结该使用哪种思想,取百家之长,才是正道。

那么AOP这种编程思想有什么用呢,一般来说,主要用于不想侵入原有代码的场景中,例如SDK需要无侵入的在宿主中插入一些代码,做日志埋点、性能监控、动态权限控制、甚至是代码调试等等。

二、AspectJ

AspectJ实际上是对AOP编程思想的一个实践,当然,除了AspectJ以外,还有很多其它的AOP实现,例如ASMDex

三、在Android项目中使用AspectJ

3.1 配置AspectJ

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'
    }
}
 
apply plugin: 'com.android.application'
 
repositories {
    mavenCentral()
}
 
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 'org.aspectj:aspectjrt:1.8.11'
}

3.2 自定义注解

package com.example.administrator.dn_02_aop;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.CLASS)
public @interface BehaviorTrace {
    String value();
    int type();
}

3.3 用@Aspect标注切面

package com.example.administrator.dn_02_aop;

import android.os.SystemClock;
import android.util.Log;
import android.view.View;

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

import java.text.SimpleDateFormat;
import java.util.Date;
/**
 * 切面
 */
@Aspect
public class BehaviorAspect

3.4 在切面类中定义PointCut(切入点)

/**
 * 切点
 */
@Pointcut("execution(@com.example.administrator.dn_02_aop.BehaviorTrace  * *(..))")
public void annoBehavior()
{

}

3.5 在切面类中定义Advance(通知)

/**
 * @param point
 * @return
 * @throws Throwable
 */
@Around("annoBehavior()")
public Object dealPoint(ProceedingJoinPoint point) throws  Throwable
{
    //获取注入参数值
    MethodSignature methodSignature= (MethodSignature) point.getSignature();
    BehaviorTrace  behaviorTrace=methodSignature.getMethod().getAnnotation(BehaviorTrace.class);
    String type=behaviorTrace.value();
    int value=behaviorTrace.type();

    //获取方法名
    String methodName = point.getSignature().toString();

    //获取参数
    Object[] objs = point.getArgs();
    int i =  ((View)objs[0]).getId();
    boolean isEquals = i==R.id.btn1;

    //打印注入参数,打印方法名
    Log.i(TAG,"type="+type+";value="+value);
    Log.i(TAG,"methodName="+methodName);

    //打印方法参数是否为Button1
    Log.i(TAG,"isEquals="+isEquals);
    Log.i(TAG,"param type="+((View)objs[0]).getClass().getName());

    //打印获取到的对象的方法
    if(point.getThis() instanceof MainActivity)
    {
        Log.i(TAG,"count="+((MainActivity)(point.getThis())).getCount());
    }


    //打印日志开始时间
    Log.i(TAG,";开始时间:"+simpleDateFormat.format(new Date()));
    Log.i(TAG,"");


    long beagin=System.currentTimeMillis();
    //方法执行时
    Object object=null;
    try {
         object=point.proceed();
    }catch (Exception e)
    {

    }

    //打印消耗时间
    Log.i(TAG,"消耗时间:  "+(System.currentTimeMillis()-beagin)+"ms");
    return  object;
}

3.6 对方法使用该注解

3.6.1 对click方法标注

/**
 * 语音的模块
 *
 * @param view
 */
@BehaviorTrace(value = Utils.STR_TEXT1,type = Utils.MSG1)
public  void doAudio(View view)
{
        SystemClock.sleep(3000);
        Log.i(TAG,"audio module");
}

3.6.2 内部类方法的标注

btn.setOnClickListener(new View.OnClickListener() {
    @BehaviorTrace(value = "onClick1",type = Utils.MSG1)
    @Override
    public void onClick(View v) {


        Log.i(TAG," 3333333");

    }
});

3.6.3 对同一个方法多个按钮处理的标注

@BehaviorTrace(value ="",type = Utils.MSG1)
@Override
public void onClick(View v) {

    switch (v.getId()){
        case R.id.btn1:
            Log.v(TAG,"onClick id="+R.id.btn1);
            break;
        case R.id.btn2:
            break;
    }
}

四、处理结果

五、项目结构

六、注入后生成的代码

猜你喜欢

转载自blog.csdn.net/u010375903/article/details/81141813