AOP之ASpectj最详细使用

AOP面向切面编程,通过预编译方式和运行期动态代理实现程序的统一维护的一种技术。

Aspectj框架就是通过预编译方式实现程序的统一维护,今天介绍如何使用:

//配置版本信息分两步,使用分三步

最新版本的aspectj是1.9.4但是需要SDK最低版本24,这里我就是使用1.8.9版本

//配置信息

1:在工程的build.gradle添加下面依赖

buildscript {
    
    repositories {
        google()
         //镜像仓,解决需要下载的
        maven { url 'http://maven.aliyun.com/nexus/content/groups/public/' }
        jcenter()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:3.2.0'
        //aspectj框架
        classpath 'org.aspectj:aspectjtools:1.8.9'
        classpath 'org.aspectj:aspectjweaver:1.8.9'

        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
    }
}

allprojects {
    repositories {
        google()
        //镜像仓,解决需要下载的
        maven { url 'http://maven.aliyun.com/nexus/content/groups/public/' }
        jcenter()
    }
}

2:在module的build.gradle添加下面依赖

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation 'com.android.support:appcompat-v7:28.0.0'
    implementation 'com.android.support.constraint:constraint-layout:1.1.3'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'com.android.support.test:runner:1.0.2'
    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'

    //使用aspectj框架
    implementation 'org.aspectj:aspectjrt:1.8.9'

}

//aspectj配置打印log

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 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
            }
        }
    }
}

//使用三部曲

1>自定义注解:根据你的需要设置注解的目标,和作用域

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface LoginTrace {
    String value() default "";

}

2>创建个切面处理类,处理所有使用注解的逻辑,统一在这个类处理

//切面
@Aspect
public class LoginAapect {

    //切入点 ("execution(@注解全类名 * *(..)")
    @Pointcut("execution(@com.example.administrator.aop_aspectj.annotation.LoginTrace *  *(..))")
    public void methodAnnotationWithLoginTrace() {
    }


    //切入点逻辑处理(可以对 切入点 前处理 后处理  前后处理 )
    //参数--->切入点方法名()--->methodAnnotationWithLoginTrace()
//    @After("methodAnnotationWithLoginTrace()")//切入点后运行 --》使用注解LoginTrace的方法运行完后执行这个方法代码
//    @Before("methodAnnotationWithLoginTrace()")//切入点前运行
    @Around("methodAnnotationWithLoginTrace()")//切入点前 后 都运行(后运行是在ProceedingJoinPoint对象非空时运行)
    public Object weaveJoinPoint(ProceedingJoinPoint joinPoint) throws Throwable {
        Log.e("zdh", "-------------前");

        Object proceed=null;
        if (joinPoint != null) {
             //如果使用Around注解需要返回proceed对象,要不然注解方法里面代码不执行
             proceed = joinPoint.proceed();
            Log.e("zdh", "-------------后");
        }

        return proceed;
    }


}

//在需要统一处理的方法添加注解

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }

  
     //如果你想区分不同方法可以使用标记区分--》@LoginTrace("send")
    @LoginTrace
    public void send(View view) {
        Log.e("zdh","------------测试");
    }
}

//运行代码就可以看到打印日志如下

AOP之ASpectj最详细使用_第1张图片

 

 是不是很简单。

总结:1:在依赖时需要注意1.9前和1.9的SDK最低版本问题,

           2:在依赖导报可以添加镜像仓看看。

           3:如果使用Around注解需要返回proceed对象,要不然注解方法里面代码不执行

           4:使用注解的方法一般是不会影响方法里面代码执行的,所以要考虑方法里面代码执行后的效果,

 

//下面以实际项目需要写个demo,一般在开发中我们有些页面是需要用户登录后才能进入的,这里面就以登录为实例写个demo

源码地址https://github.com/zhudaihao/AOP_aspectj

你可能感兴趣的:(工具,控件)