Android面向切面AspectJ

Posted ljt2724960661

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android面向切面AspectJ相关的知识,希望对你有一定的参考价值。

        这一节主要了解一下AspectJ技术,它属于AOP(Aspect Oriented Programming)技术,意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。最先是应用在Java后端,如Spring,在android中一般应用场景如方法耗时,统计埋点,日志打印/打点;使用这个技术的原因是它能够降低代码耦合度,提高程序的可重用性,同时提高了开发的效率;

 AOP常用API:

@Aspect:声明切面,标记类
@Pointcut(切点表达式):定义切点,标记方法
@Before(切点表达式):前置通知,切点之前执行
@Around(切点表达式):环绕通知,切点前后执行
@After(切点表达式):后置通知,切点之后执行
@AfterReturning(切点表达式):返回通知,切点方法返回结果之后执行
@AfterThrowing(切点表达式):异常通知,切点抛出异常时执行

注:如果没有添加@Aspect,那么后面的注解一律不起作用

一般使用步骤如下:

1 项目下添加依赖
2 App下添加依赖
3 创建切面类
4 实现拦截业务
注:execution(<修饰符><返回类型><包.类.方法(参数)><异常>) //修饰符和异常可以省略

栗子:

项目下gradle:

buildscript 
    repositories 
        mavenCentral()
    
    dependencies 
        classpath 'org.aspectj:aspectjtools:1.8.9'
        classpath 'org.aspectj:aspectjweaver:1.8.9'
    
app下gradle:

implementation 'org.aspectj:aspectjrt:1.8.9'


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;
            
        
    
import android.util.Log;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;

@Aspect
public class CheckAspectJ 
    private static final String TAG = "CheckAspectJ";

    @Pointcut("execution(* *.test())")
    public void pointcut() 
        Log.i(TAG,"@pointcut");
    
// Log.i(TAG,

    @Before("pointcut()")
    public void before(JoinPoint point) 
        Log.i(TAG,"@Before");
    

    @Around("pointcut()")
    public void around(ProceedingJoinPoint joinPoint) throws Throwable 
        Log.i(TAG,"@Around");
        joinPoint.proceed();
        Log.i(TAG,"@Around----->>> end");
    

    @After("pointcut()")
    public void after(JoinPoint point) 
        Log.i(TAG,"@After");
    

    @AfterReturning("pointcut()")
    public void afterReturning(JoinPoint point, Object returnValue) 
        Log.i(TAG,"@AfterReturning returnValue="+returnValue
                +"  point = "+point);
    

//    @AfterThrowing(value = "pointcut()", throwing = "ex")
//    public void afterThrowing(Throwable ex) 
//        Log.i(TAG,"@afterThrowing");
//        Log.i(TAG,"ex = " + ex.getMessage());
//    

    @AfterThrowing(value = "pointcutThreadTest()", throwing = "ex")
    public void afterThrowing(Throwable ex) 
        Log.i(TAG,"@afterThrowing");
        Log.i(TAG,"ex = " + ex.getMessage());
    

    @Pointcut("execution(* com.sky.aopshow.MainActivity.threadTest())")
    public void pointcutThreadTest() 
    
    @Around("pointcutThreadTest()")
    public void calculateFunctionTime(ProceedingJoinPoint joinPoint) throws Throwable 
        Log.i(TAG,"pointcut1 ---------calculateFunctionTime---------@Around");
        long beginTime = System.currentTimeMillis();
        joinPoint.proceed();
        long endTime = System.currentTimeMillis();
        Log.i(TAG,"pointcut1 -----------calculateFunctionTime-------运行时间:" + (endTime - beginTime));
    
  private void initView() 
        button1 = findViewById(R.id.button1);
        button2 = findViewById(R.id.button2);
        button3 = findViewById(R.id.button3);
        button4 = findViewById(R.id.button4);

        button1.setOnClickListener(new View.OnClickListener() 
            @Override
            public void onClick(View v) 
                test();
            
        );

        button2.setOnClickListener(new View.OnClickListener() 
            @Override
            public void onClick(View v) 
               threadTest();
            
        );
        button3.setOnClickListener(new View.OnClickListener() 
            @Override
            public void onClick(View v) 
                stepOn1();
                stepOn2("小明");
                stepOn3("小明", 18);
            
        );
        button4.setOnClickListener(new View.OnClickListener() 
            @Override
            public void onClick(View v) 
//                CheckAspectJ.isLoagin = !CheckAspectJ.isLoagin;
            
        );
    

    public void test() 
         Log.i(TAG,"Hello,Decard Terminal...");
    

    private void stepOn1() 
         Log.i(TAG,"stepOn1");
    

    private void stepOn2(String name) 
         Log.i(TAG,"stepOn2");
    

    private void stepOn3(String name, int i) 
         Log.i(TAG,"stepOn3");
    


    public void threadTest() 
        System.out.println("Hello, AOP TANK");
        int a = 1 / 0;      
    

原理:AspectJ意思是Java的Aspect java的AOP,它其实不是一个新的语言,它的核心ajc(编译器)\\weaver(织入器);ajc编译器: 基于Java编译器之上的,它是用来编译.aj文件,aspectj在Java编译器的基础上增加了一些它自己的关键字和方法。因此,  ajc也可以编译Java代码。weaver织入器:为了在Java编译器上使用AspectJ而不依赖于Ajc编译器,aspectJ5 出现了@AspectJ,使用注释的方式编写AspectJ代码,可以在任何Java编译器上使用;

以上是关于Android面向切面AspectJ的主要内容,如果未能解决你的问题,请参考以下文章

面向切面编程:aspectJ在Android中的使用

面向切面编程:aspectJ在Android中的使用

Android AOP 面向切面编程 - AspectJ

AOP 面向切面编程Android Studio 使用 AspectJ 监控方法运行原理分析

AOP 面向切面编程Android Studio 中配置 AspectJ ( 下载并配置AS中 jar 包 | 配置 Gradle 和 Gradle 插件版本 | 配置 Gradle 构建脚本 )(代

AOP 面向切面编程Android Studio 使用 AspectJ 监控方法运行 ( 定义连接点注解 | 定义 Aspect 切面 | 定义切入点 | 逐个处理切入点的各个连接点 )