AOP之ASpectj最详细使用

95 篇文章 0 订阅

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添加下面依赖

apply plugin: 'com.android.application'

android {
    compileSdkVersion 29
    buildToolsVersion "30.0.0"

    defaultConfig {
        applicationId "com.example.myaspectj"
        minSdkVersion 16
        targetSdkVersion 29
        versionCode 1
        versionName "1.0"

        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    implementation fileTree(dir: "libs", include: ["*.jar"])
    implementation 'androidx.appcompat:appcompat:1.2.0'
    implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'androidx.test.ext:junit:1.1.2'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'

    //使用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对象非空时运行) (必须返回object对象)
    public Object weaveJoinPoint(ProceedingJoinPoint joinPoint) throws Throwable {
        Log.e("zdh", "-------------前");
         //如果想要获取自定义注解属性值 必须使用@Around 通过ProceedingJoninPoint获取
         //例如
         LoginTrace loginTrace=((MethodSignarure)joinPoint.getSignature()).getMethod().getAnnotation(LoginTrace.class);//获取自定义注解对象
         String value=loginTrace.value();//注解属性值
        


        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","------------测试");
    }
}

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

注意混淆 在项目的build.build里面配置 扫描指定文件,防止扫描其他文件导致错误

aspectjx {
    //指定只对含有关键字'universal-image-loader', 'AspectJX-Demo/library'的库进行织入扫描,忽略其他库,提升编译效率
//    includeJarFilter 'universal-image-loader', 'AspectJX-Demo/library'
        include 'com.gemini'
        exclude 'com.amitshekhar'
        exclude 'com.mobile'
        exclude 'com.nirvana'
        exclude 'com.cmic'
        exclude 'com.unicom'
//    excludeJarFilter '.jar'
//    ajcArgs '-Xlint:warning'
}

 

 

 

 是不是很简单。

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

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

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

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

 

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

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

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值