Android收藏集

Android AOP:最简单&粗暴(使用与原理)讲解

2018-12-13  本文已影响346人  Linhaojian

1.前言


2.介绍

2.1 AOP 是什么

2.2 AOP 作用

2.3 AOP 特点

2.4 Android 中应用

2.5 AOP 术语

2.6 AOP 注解

@Pointcut、@Before、@Around、@After、@AfterReturning、@AfterThrowing需要在切面类中使用,即在使用@Aspect的类中。

2.7 切点表达式

AspectJ语法1.png
AspectJ语法2.png
AspectJ语法3.png
    // 返回类型:*  类名+函数名:com.lhj.test_apt..*ck(..)   
    //  com.lhj.test_apt..*ck(..)  :意思是com.lhj.test_apt包下所有类中以ck结尾的函数
    @Pointcut("execution(*  com.lhj.test_apt..*ck(..))")

3.使用

    dependencies {
        classpath 'org.aspectj:aspectjtools:1.8.13'    // add
        classpath 'org.aspectj:aspectjrt:1.8.13'       // add
    }
apply plugin: 'com.android.library'
import org.aspectj.bridge.IMessage
import org.aspectj.bridge.MessageHandler
import org.aspectj.tools.ajc.Main
android {
    compileSdkVersion 28
    defaultConfig {
        minSdkVersion 17
        targetSdkVersion 28
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}
dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    // aop
    implementation 'org.aspectj:aspectjrt:1.8.13'
}
project.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", 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;
            }
        }
    }
}
/**
 * 添加切面注解
 */
@Aspect
public class AopTest {
    private static final String TAG = "linhaojian";
    /**
     * 定义切入点(定义那些类或者方法需要改变)
     */
    @Pointcut("execution(*  com.lhj.test_apt..*ck(..))")
    public void pointcut1() {
    }
    /**
     * 使用注解方式,定义注解
     */
    @Pointcut("execution(@com.lhj.test_apt.DebugLog * *ck(..))")
    public void pointcut() {
    }
    /**
     * 前置通知,切点之前执行
     * @param point
     */
    @Before("pointcut()")
    public void logBefore(JoinPoint point){
        Log.e(TAG,"logBefore");
    }
    /**
     * 环绕通知,切点前后执行
     * @param joinPoint
     * @throws Throwable
     */
    @Around("pointcut()")
    public void logAround(ProceedingJoinPoint joinPoint) throws Throwable {
        Log.e(TAG,"logAround");
        // 1.执行切点函数(如果不调用该方法,切点函数不被执行)
        joinPoint.proceed();
    }
    /**
     * 后置通知,切点之后执行
     * @throws Throwable
     */
    @After("pointcut()")
    public void logAfter(JoinPoint point){
        Log.e(TAG,"logAfter");
    }
    /**
     * 返回通知,切点方法返回结果之后执行
     * @throws Throwable
     */
    @AfterReturning("pointcut()")
    public void logAfterReturning(JoinPoint point, Object returnValue){
        Log.e(TAG,"logAfterReturning ");
    }
    /**
     * 异常通知,切点抛出异常时执行
     * @throws Throwable
     */
    @AfterThrowing(value = "pointcut()",throwing = "ex")
    public void logAfterThrowing(Throwable ex){
        Log.e(TAG,"logAfterThrowing : "+ex.getMessage());
    }
}
public class AopActivity extends AppCompatActivity {
    private Button button;
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.aop);
        button = findViewById(R.id.button);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                click();
            }
        });
    }
    @DebugLog
    public void click(){
        Log.e("linhaojian","onClick()");
    }
}
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface DebugLog {
}

4.原理

public class AopActivity extends AppCompatActivity {
    private Button button;
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        this.setContentView(layout.aop);
        this.button = (Button)this.findViewById(id.button);
        this.button.setOnClickListener(new OnClickListener() {
            public void onClick(View v) {
                AopActivity.this.click();
            }
        });
    }
    @DebugLog
    public void click() {
        // 1
        JoinPoint var1 = Factory.makeJP(ajc$tjp_0, this, this);
        try {
            try {
                // 2
                AopTest.aspectOf().logBefore(var1);
               // 3
                click_aroundBody1$advice(this, var1, AopTest.aspectOf(), (ProceedingJoinPoint)var1);
            } catch (Throwable var4) {
                AopTest.aspectOf().logAfter(var1);
                throw var4;
            }
            AopTest.aspectOf().logAfter(var1);
            AopTest.aspectOf().logAfterReturning(var1, (Object)null);
        } catch (Throwable var5) {
            AopTest.aspectOf().logAfterThrowing(var5);
            throw var5;
        }
    }
}
@Aspect
public class AopTest {
    //...
    public static AopTest aspectOf() {
        if (ajc$perSingletonInstance == null) {
            throw new NoAspectBoundException("com.lhj.test_apt.AopTest", ajc$initFailureCause);
        } else {
            return ajc$perSingletonInstance;
        }
    }
    public static boolean hasAspect() {
        return ajc$perSingletonInstance != null;
    }
    static {
        try {
            // 4
            ajc$postClinit();
        } catch (Throwable var1) {
            ajc$initFailureCause = var1;
        }
    }
}

5.总结

欢迎关注linhaojian_CSDN博客或者linhaojian_简书

不定期分享关于安卓开发的干货。


写技术文章初心

  • 技术知识积累
  • 技术知识巩固
  • 技术知识分享
  • 技术知识交流
上一篇 下一篇

猜你喜欢

热点阅读