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

面向切面编程:aspectJ在Android中的使用,第1张

概述一、简介和使用场景aspectJ 是eclipse社区中的一个开源工具,可以对java编程语言面向切面进行无缝拓展、完全兼容java语言,它可以对关注切点进行优雅处理,比如错误检查与处理、性能优化、监视与日志记录等场景。说到面向切面编程,大家可能会联想到著名的SpringAOP,SpringAOP是基 一、 简介和使用场景

aspectJ 是eclipse社区中的一个开源工具,可以对java编程语言面向切面进行无缝拓展、完全兼容java语言,它可以对关注切点进行优雅处理,比如错误检查与处理、性能优化、监视与日志记录等场景。说到面向切面编程,大家可能会联想到著名的Spring AOP,Spring AOP是基于动态代理模式实现的。代理模式分为静态代理和动态代理,静态代理在编译期修改代码将指定对象注入到代码中,拓展性差、耦合性强;动态代理在运行时通过反射动态获取对象并调用其方法,效率低、耦合性强,Spring AOP通过IOC依赖注入技术一定程度上解决了耦合的问题,但是执行效率没有得到解决;aspectJ在编译期修改代码,并且和业务逻辑代码分离,耦合性强,并且不影响运行时的效率。JakeWharton大神的函数耗时监控开源项目hugo 就使用了aspectJ技术。

二 、基本概念2.0 注解

在手动实现bindview一文用到了注解,现在越来越觉得注解用处真大,注解的具体使用可以参考我之前的文章 注解 ,这里我创建一个运行时注解。

//CheckNet.java@Retention(RetentionPolicy.RUNTIME)@Target(ElementType.METHOD)public @interface CheckNet {}

2.1 Aspect 切面

切面是切入点和通知的集合,@Aspect 用它声明一个类,表示一个需要执行的切面,比如我这里创建一个类,并在类的顶部添加@Aspect注解。

//MyAspect.java@Aspectpublic class MyAspect {}
2.2 pointcut 切入点

切入点又称触发条件,是指那些通过使用一些特定的表达式过滤出来的想要切入Advice的连接点,@pointcut 声明一个切点。

 

 

 

 

 

 

 

 

 

  

 

 这里我想做个网络判断的逻辑

//MyAspect.java@pointcut("execution(@com.shan.aspectjapp.CheckNet * *(..))")public voID checkNetAction(){}

 在pointcut这里,我使用了execution,也就是以方法执行时为切点,触发Aspect类。而execution里面的字符串是触发条件,也是具体的切点。我来解释一下参数的构成。"execution(@com.shan.aspectjapp.CheckNet * *(..))"这个条件是所有加了CheckNet 注解的方法或属性都会是切点,范围比较广。

* *:表示是任意包名..:表示任意类型任意多个参数2.3 Advice 通知

通知是向切点中注入的代码实现方法,@Before/@After/@Around/...(统称为Advice类型) 声明在切点前、后、中执行切面代码,详细见下表:

Before

前置通知, 在目标执行之前执行通知

After

后置通知, 目标执行后执行通知

Around

环绕通知, 在目标执行中执行通知, 控制目标执行时机

AfterReturning

后置返回通知, 目标返回时执行通知

AfterThrowing

异常通知, 目标抛出异常时执行通知

这里使用@Around在目标代码执行时去判断是否有网络,如果没网络则不再执行目标方法,否则执行目标方法

@Around("checkNetAction()")public Object checkNet(ProceedingJoinPoint joinPoint) throws Throwable {    MethodSignature signature = (MethodSignature) joinPoint.getSignature();    CheckNet checkNet = signature.getmethod().getAnnotation(CheckNet.class);    LogUtil.d("checkNet,"+checkNet);    if (checkNet!=null) {         if (!isNetworkAvailable()) {            Toast.makeText(MyApp.getContext(),"please check your network",Toast.LENGTH_SHORT).show();            return null; //无网络则目标方法不再继续执行        }    }    return joinPoint.proceed(); //有网络则继续执行目标方法}
2.4 Joint Point 连接点

所有的目标方法都是连接点.

2.5 Weaving 编织

主要是在编译期使用AJC将切面的代码注入到目标中, 并生成出代码混合过的.class的过程.

三、 androID中使用3.1 下载并安装aspectJ

可以在aspectJ官网上下载aspectj.jar,然后双机一路next直到安装成功,本人这里下载的是1.9.6版本,安装后在安装目录 找到aspectjrt.jar后面在androID工程中会用到这个jar。

 

 

3.2 配置androID依赖

首先工程根目录的build.gradle中添加aspectJ依赖

//build.gradle// top-level build file where you can add configuration options common to all sub-projects/modules.buildscript {    ……    dependencIEs {        classpath "com.androID.tools.build:gradle:4.2.1"        //重点是下面两行        classpath 'org.aspectj:aspectjtools:1.9.6'        classpath 'org.aspectj:aspectjweaver:1.9.6'    }}

 

然后在主module的build.gradle添加依赖和环境

//build.gradleplugins {    ID 'com.androID.application'}//重点下面三行import org.aspectj.brIDge.IMessageimport org.aspectj.brIDge.MessageHandlerimport org.aspectj.tools.ajc.Main……//然后是下面一坨final def log = project.loggerfinal def variants = project.androID.applicationVariantsvariants.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;            }        }    }}

最后将aspectjrt.jar放到libs目录并添加依赖

3.3 使用

然后在activity中点击登陆,如果无网络则下面的"we will surf the Internet"提示就不会走到,而会提示MyAspect.java中的"please check your network";如果有网络则会提示"we will surf the Internet".

//MainActivity.javapublic class MainActivity extends AppCompatActivity {    @OverrIDe    protected voID onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentVIEw(R.layout.activity_main);    }    @CheckNet //这就是面向切面编程了    public voID login(VIEw vIEw) {        Toast.makeText(this,"we will surf the Internet",Toast.LENGTH_SHORT).show();    }}

 参考:

安卓架构师必备之Android AOP面向切面编程详解,超实用!

 

总结

以上是内存溢出为你收集整理的面向切面编程:aspectJ在Android中的使用全部内容,希望文章能够帮你解决面向切面编程:aspectJ在Android中的使用所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/web/1107983.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-29
下一篇 2022-05-29

发表评论

登录后才能评论

评论列表(0条)

保存