AOP For Android -基于AspectJ

本文旨在帮助Andoird开发者快速实现AOP开发,少走弯路欢迎点赞和收藏。

网上关于AspectJ的介绍已经很多了,本文就不做过多介绍了。有兴趣的同学可以参考以下链接,感谢大神分享

自定义注解学习 : https://www.cnblogs.com/peida/archive/2013/04/26/3038503.html

AspectJ 自己去找找吧 !网上文章一堆一堆的

先简单说一下需求吧

在开发的时候,我们经常会遇到登录拦截的业务逻辑,简单说就是有些功能必须需要登录才能使用,有些功能不需要登录。在OOP 面向对象的编程开发中,我们可能需要定义一个工具类,然后在需要登录的地方做一些判断,比如:

if (LoginUtils.isLogin()){
  //已经登录 处理正常逻辑

}else{
//未登录 跳转登录页面
}

这样处理起来是完全没有任何问题的,也能够达到拦截的目的,但是这样写代码耦合性太强,不够优雅,而且代码量也超多,所以下边我来简单介绍一下在Android中怎么样来使用AOP思想来实现登录拦截的逻辑。

1、 在项目的 build.gradle中添加 :

    dependencies {
        ......
        classpath 'org.aspectj:aspectjtools:1.8.10'
        classpath 'org.aspectj:aspectjweaver:1.8.8'
    }

2、 在app的build.gradle中添加依赖 :

    dependencies {
        //aop
    implementation 'org.aspectj:aspectjrt:1.9.5'
    }

3、还需要引入在app的build.gradle中引入以下内容 (最外层添加即可)

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
    variant.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;
            }
        }
    }
}

4、同步一下之后,准备撸码 :
4.1、首先我们定义一个LoginTrace的自定义注解(不了解的小童鞋自己抓紧学习)

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface LoginTrace {
     int type() default -1;
}

根据自己的业务需求来吧,当然也可以不需要添加type属性
4.2、接下来我们需要定义一个 LoginAspect 的切面,直接上代码

@Aspect
public class LoginAspect {
    /**
     * 对含有某个方法的特定注解打上切点
     */
@Pointcut("execution(@com.sdzte.mvparchitecture.aop.LoginTrace * *(..))")
   // @Pointcut(POINTCUT_ONMETHOD)
    public void pointCutLogin(){
     
    }

    /**
     * 处理 特定的打上切点的方法
     * @param proceedingJoinPoint
     * @throws Throwable
     */
    @Around("pointCutLogin()")
    public void aroundLogin(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
// 这一步判断比较暴力,大家根据自己需要判断把
        if (!TextUtils.isEmpty(CommonUtils.getUserToken())){
            proceedingJoinPoint.proceed();
        }else {
                // 获得注解参数
                MethodSignature signature = (MethodSignature) proceedingJoinPoint.getSignature();
                LoginTrace annotation = signature.getMethod().getAnnotation(LoginTrace.class);
                int type = annotation.type();
                dealWithType(type);
        }
    }

    /**
     * 在这里处理
     * @param type
     */
    private void dealWithType(int type){
        switch (type){
            case 0:
                Intent intent = new Intent(MyApplication.getContext(), LoginActivity.class);
                intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                MyApplication.getContext().startActivity(intent);
                break;
            default:

                break;
        }
    }
}

4.3、 经过几步简单的配置时候我们就可以愉快的玩耍了,下面是使用方法:

  btnTest.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                testLogin();
            }
        });
......

   @LoginTrace(type = 0)
    public void testLogin(){
      //登录之后的流程

    }

5、 欢迎大家点赞和收藏,不明白的问题留言。

你可能感兴趣的:(AOP For Android -基于AspectJ)