一般情况我们的App里面在各个界面会有判断是否登录,如果用户登录过了直接进行下一步操作,如用户没有登录则跳转到登录界面,或者在用户操作某一步时手机相关信息等,我们都可以使用AOP切面进行处理。

例如之前我们这么写:

if(isLogin) {
            // 如果登录才跳转,进入我的关注页面
            Intent intent = new Intent(this, SecondActivity.class);
            startActivity(intent);
        }else{
            //跳转到登录页面,先登录
            Intent intent = new Intent(this, LoginActivity.class);
            startActivity(intent);
        }

这样我们如果这样处理,代码量上会增加很多,不断的写着重复的代码,

现在我们这样写,通过AOP注解方式:

@UserInfoGet()
 public void loginTo(View view) {
       Log.d("UserInfoAspectJ"," ------loginTo----->执行登录呦" );
       Intent intent = new Intent(this, SecondActivity.class);
       startActivity(intent);
 }

AspectJ

AspectJ实际上是对AOP编程思想的一个实践,AOP虽然是一种思想,但就好像OOP中的Java一样,一些先行者也开发了一套语言来支持AOP。目前用得比较火的就是AspectJ了,它是一种几乎和Java完全一样的语言,而且完全兼容Java(AspectJ应该就是一种扩展Java,但它不是像Groovy那样的拓展。)。当然,除了使用AspectJ特殊的语言外,AspectJ还支持原生的Java,只要加上对应的AspectJ注解就好。所以,使用AspectJ有两种方法: 
- 完全使用AspectJ的语言。这语言一点也不难,和Java几乎一样,也能在AspectJ中调用Java的任何类库。AspectJ只是多了一些关键词罢了。 
- 或者使用纯Java语言开发,然后使用AspectJ注解,简称@AspectJ

基础概念 
- Aspect 切面:切面是切入点和通知的集合。

  • PointCut 切入点:切入点是指那些通过使用一些特定的表达式过滤出来的想要切入Advice的连接点。
  • Advice 通知:通知是向切点中注入的代码实现方法。
  • Joint Point 连接点:所有的目标方法都是连接点.
  • Weaving 编织:主要是在编译期使用AJC将切面的代码注入到目标中, 并生成出代码混合过的.class的过程.

使用:

首先是app的build.gradle增加以下内容:

先增加一个依赖包:


implementation 'org.aspectj:aspectjrt:1.9.4'


然后在增加下面的内容,下面的内容直接全部复制,然后粘贴到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

buildscript {
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath 'org.aspectj:aspectjtools:1.9.4'
        classpath 'org.aspectj:aspectjweaver:1.9.4'
    }
}
//在构建工程时,执行编辑
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.9",
                         "-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;
            }
        }
    }
}

上面的直接放在你的build.gradle中最下面,不需要放在已有的大括号中,看一下:

android 验证账号密码是否正确 android验证登录跳转_Java

然后编译,编译好了后会报一个提醒,不需要管它,然后接着写重要内容:

1、先写一个    BehaviorOne  ,然后加上注解,


@Target(ElementType.METHOD) 是表示注解是在哪里起作用,这里是METHOD表示在方法上加注解


@Retention(RetentionPolicy.RUNTIME) 表示在运行时处理


在创建的时候这些选:

android 验证账号密码是否正确 android验证登录跳转_Android_02

写好之后是这样的:

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.RUNTIME)
public @interface BehaviorOne {

}

2、然后在定义一个类   UserInfoAspectJ:

import android.util.Log;
import com.wwy.mytestapp.apo.BehaviorOne;
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.MethodSignature;

@Aspect
public class UserInfoAspectJ {

    boolean isLogin = false;

    /**
     * //找到处理的切入点
     */
    @Pointcut("execution(@com.wwy.mytestapp.apo.BehaviorOne * *(..))")
    public void methodWithBehavior(){

    }

    /**
     * 处理切面
     * @param joinPoint
     * @return
     * @throws Throwable
     */
    @Around("methodWithBehavior()")
    public Object isLogin(ProceedingJoinPoint joinPoint) throws Throwable{
        Log.e("UserInfoAspectJ"," :  进入切面====----===");
        MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
        //根据方法名拿到注解
        BehaviorOne behaviorOne = methodSignature.getMethod().getAnnotation(BehaviorOne.class);

        // 判断当前用户是否登录
        if (behaviorOne != null) {
            if (!isLogin) {
                Log.e("UserInfoAspectJ", " :  未登录,请先登录。");
                isLogin = true;
                return  null;
            } else {
                Log.e("UserInfoAspectJ", " :  已登录,-------》 ");
                return joinPoint.proceed();
            }
        }
        return joinPoint.proceed();
    }
}

3、下面就是在activity中处理了,我这里简单的写了一个button登录按钮,

<Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="点击登录"
        android:layout_marginTop="15dp"
        android:onClick="loginTo"/>

然后在activity中的点击方法是这样:

@BehaviorOne()
    public void loginTo(View view) {
        Log.d("UserInfoAspectJ"," ------loginTo----->执行登录呦" );

    }

然后当用户点击的登录按钮的时候,它不会立刻打印上面的   执行登录呦  ,而是先执行    UserInfoAspectJ 类,然后执行其中的  isLogin  方法 ,里面有进行判断处理。如果未登录会先打印: 


Log.e("UserInfoAspectJ", " : 未登录,请先登录。");


若已登录,则直接执行点击事件里面的代码。

基本思路就是这些了。在此做个记录,下次好直接使用。