Android Kotlin使用AspectJ进行AOP面向切面编程

news2024/11/28 12:32:02

前言

什么是面向切面编程?首先我们来了解下两个概念:
OOP(面向对象编程):针对业务处理过程的实体及其属性和行为进行抽象封装,以获得更加清晰高效的逻辑单元划分。
AOP(面向切面编程):则是针对业务处理过程中的切面进行提取,它所面对的是处理过程中的某个步骤或阶段,以获得逻辑过程中各部分之间低耦合性的隔离效果。

由此可知,利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。

配置AspectJ以及报错处理

这里,我们就使用AspectJ进行切面编程,其相对应的github地址:hujiang.aspectjx

配置步骤如下:

  1. 根目录build.gradle中添加 classpath 'com.hujiang.aspectjx:gradle-android-plugin-aspectjx:2.0.10'
  2. 对应app模块build.gradle 添加:
apply plugin: 'android-aspectjx'
implementation 'org.aspectj:aspectjrt:1.8.9'

AspectJ配置
当然如果按照以上配置就可以编译通过,那要先祝贺你了,这里我记录下我配置后编译报错的一些问题:

> Failed to apply plugin 'android-aspectjx'.
   > Build was configured to prefer settings repositories over project repositories but repository 'MavenLocal' was added by plugin 'android-aspectjx'

解决方案: 替换setting.gradle文件dependencyResolutionManagement配置中 repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)repositoriesMode.set(RepositoriesMode.PREFER_SETTINGS)
aspect问题1

Cause: zip file is empty

解决方案:对应app模块添加配置

aspectjx{
        exclude 'org.jetbrains.kotlin', "module-info", 'versions.9'
    }

aspect问题2
经过上述的配置,我们就可以开始使用AspectJ进行切面编程了!!!

一个小栗子

这里,我们举个简单又实际开发中会碰到的案例:
比如在开发中,碰到很多地方需要先判断当前是否有网络,如果没有网络就弹Toast,有网络的时候才进行对应界面跳转!
那怎么去处理这类问题呢?我们常用的做法是一个个地方去进行判断是否有网络,这样如果需求进行变动,就会很麻烦,同时这种做法也不太优雅。
下面我们就使用AspectJ来解决这个问题;

  • 首先定义CheckNet注解
package com.crystal.essayjoker.aop
@Retention(AnnotationRetention.RUNTIME)
@Target(AnnotationTarget.FUNCTION)
annotation class CheckNet()
  • CheckNet注解进行界面处理
package com.crystal.essayjoker.aop

import android.app.Activity
import android.content.Context
import android.net.ConnectivityManager
import android.net.NetworkInfo
import android.util.Log
import android.view.View
import android.widget.Toast
import androidx.fragment.app.Fragment
import org.aspectj.lang.ProceedingJoinPoint
import org.aspectj.lang.annotation.Around
import org.aspectj.lang.annotation.Aspect
import org.aspectj.lang.annotation.Pointcut

@Aspect
class CheckNetAspect {
   /**
    * 找到要处理的切点
    *  * *(..)表示可以处理所有的方法 比如有参无参的
    */
   @Pointcut("execution(@com.crystal.essayjoker.aop.CheckNet * *(..))")
   fun checkNetBehavior() {

   }

   /**
    * 处理切面
    */
   @Around("checkNetBehavior()")
   fun checkNetRound(joinPoint: ProceedingJoinPoint): Any? {
       Log.e("CheckNetAspect", "checkNetRound")
       val target = joinPoint.`this` //获取当前切点所在的类
       val context = getContext(target)
       if (context != null) {
           if (!isNetworkAvailable(context)) {
               Toast.makeText(context, "请检查网络是否正常", Toast.LENGTH_SHORT).show()
               return null
           }
       }
       return joinPoint.proceed()
   }

   private fun getContext(target: Any): Context? {
       return when (target) {
           is Activity -> {
               target
           }
           is Fragment -> {
               target.context
           }
           is View -> {
               target.context
           }
           else -> null
       }
   }

   /**
    * 判断网络是否可用
    */
   private fun isNetworkAvailable(context: Context): Boolean {
       // 获取手机所有连接管理对象(包括对wi-fi,net等连接的管理)
       val connectivityManager =
           context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
       // 获取NetworkInfo对象
       val networkInfo = connectivityManager.allNetworkInfo
       if (networkInfo.isNotEmpty()) {
           for (i in networkInfo.indices) {
               // 判断当前网络状态是否为连接状态
               if (networkInfo[i].state == NetworkInfo.State.CONNECTED) {
                   return true
               }
           }
       }
       return false
   }

}
  • 测试验证
class CheckNetActivity : AppCompatActivity() {
   override fun onCreate(savedInstanceState: Bundle?) {
       super.onCreate(savedInstanceState)
       setContentView(R.layout.activity_check_net)
       findViewById<Button>(R.id.btn).setOnClickListener {
           onCheckNet()
       }
   }

   @CheckNet
   fun onCheckNet() {
       Toast.makeText(this@CheckNetActivity, "跳转到其他界面", Toast.LENGTH_SHORT).show()
   }
}

测试结果:点击按钮时,会去检查网络,没有会提示请检查网络是否正常,有网则会提示跳转到其他界面!

AspectJ实现原理

上面我们简单实用AspectJ进行了切面编程,那咱一定很好奇它是如何做到切面处理的呢?我们使用jadx反编译生成的APK,找到CheckNetActivity中的onCheckNet方法

  private static final /* synthetic */ void onCheckNet_aroundBody0(CheckNetActivity ajc$this, JoinPoint joinPoint) {
        Toast.makeText(ajc$this, "跳转到其他界面", 0).show();
    }

    private static final /* synthetic */ Object onCheckNet_aroundBody1$advice(CheckNetActivity ajc$this, JoinPoint thisJoinPoint, CheckNetAspect ajc$aspectInstance, ProceedingJoinPoint joinPoint) {
        Intrinsics.checkNotNullParameter(joinPoint, "joinPoint");
        Log.e("CheckNetAspect", "checkNetRound");
        Object target = joinPoint.getThis();
        Intrinsics.checkNotNullExpressionValue(target, TypedValues.AttributesType.S_TARGET);
        Context context = ajc$aspectInstance.getContext(target);
        if (context == null || ajc$aspectInstance.isNetworkAvailable(context)) {
            onCheckNet_aroundBody0(ajc$this, joinPoint);
            return null;
        }
        Toast.makeText(context, "请检查网络是否正常", 0).show();
        return null;
    }

可以看出在编译时AspectJ将代码插入到onCheckNet方法中,由此实现了切面编程!

小结

如果以上文章对您有一点点帮助,希望您不要吝啬的点个赞加个关注,您每一次小小的举动都是我坚持写作的不懈动力!ღ( ´・ᴗ・` )

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/88232.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

html好看的生日祝福,生日表白(源码)

文章目录1.设计来源1.1 主界面1.2 秘密基地1.3 甜言蜜语2.效果和源码2.1 动态效果2.2 源代码2.3 自定义背景图片代码2.4 自定义每次生日记录代码2.5 自定义背景音乐代码源码下载作者&#xff1a;xcLeigh 文章地址&#xff1a;https://blog.csdn.net/weixin_43151418/article/de…

Java实现Google第三方登录

文章目录前言一、了解OAuth2.0二、注册开发者账号1.登录开发者平台2.创建应用三、代码实现1.实现流程1.点击登录2.接受回调中的code获取accessToken3.获取用户信息2.注意事项前言 Google API 使用 OAuth 2.0 协议进行身份验证和授权。Google 支持常见的 OAuth 2.0 场景&#x…

高分子点击试剂DBCO-PEG-Hydrazide,二苯并环辛炔-聚乙二醇-酰基

一、试剂基团反应特点&#xff08;Reagent group reaction characteristics&#xff09;&#xff1a; DBCO-PEG-Hydrazide属于高分子点击试剂&#xff0c;“点击化学"一般由叠氮化物&#xff08;azide&#xff09;和炔烃&#xff08;alkyne&#xff09;作用形共价键&#…

老港综合填埋场二期配套渗滤液工程电能管理系统的设计和应用-Susie 周

1、概述 本项目为老港综合填埋场二期配套渗滤液工程电能管理系统。根据配电系统管理的要求&#xff0c;需要对&#xff08;老港综合填埋场二期配套渗滤液工程电能管理系统项目的配电柜进行电能管理&#xff0c;以保证用电的安全、可靠。 Acrel-3000电能管理系统充分利用了现代…

Mybatis源码分析(一)Mybatis 基本使用

目录一 知识回顾1.1 简介1.2 其他二 基本使用官网&#xff1a;mybatis – MyBatis 3 | 简介 一 知识回顾 1.1 简介 MyBatis 是一款优秀的持久层框架&#xff0c;它支持自定义 SQL、存储过程以及高级映射。MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作…

图片怎么转换成excel文档?

当我们创建excel文档中&#xff0c;里面无疑是需要各种表格内容&#xff0c;而如果是我们一个一个编辑起来&#xff0c;这就会比较繁琐。而现在许多需求可以通过网络很容易地得到满足。比如有把图片转换成excel表格的需求。下载一个小工具&#xff0c;这就相当方便了&#xff0…

不愧是阿里资深架构师,这本“分布式架构笔记”写得如此透彻明了

前言&#xff1a; Mybatis 是一款优秀的持久层框架。其封装了 JDBC 操作&#xff0c; 免去了开发人员编写 JDBC 代码以及设置参数和获取结果集的重复性工作。通过编写简单的 XML 或 Java 注解即可映射数据库 CRUD 操作。本文介绍的是阿里资深架构师十年经验整理&#xff0c;My…

JAVA 中的注解可以继承吗?

前言 注解想必大家都用过&#xff0c;也叫元数据&#xff0c;是一种代码级别的注释&#xff0c;可以对类或者方法等元素做标记说明&#xff0c;比如 Spring 框架中的Service&#xff0c;Component等。那么今天我想问大家的是类被继承了&#xff0c;注解能否继承呢&#xff1f;…

基于springboot在线答疑系统

教师权限&#xff1a;首页、个人中心、疑难解答管理、试卷管理、试题管理、考试管理。 学生权限&#xff1b;首页、个人中心、问题发布管理、疑难解答管理、考试管理等功能模块的管理维护等操作&#xff0c;系统结构图如下图4-1所示。 图4-1 系统功能图 截图 目 录 摘 要 I …

[附源码]Node.js计算机毕业设计扶贫产品展销平台小程序Express

项目运行 环境配置&#xff1a; Node.js最新版 Vscode Mysql5.7 HBuilderXNavicat11Vue。 项目技术&#xff1a; Express框架 Node.js Vue 等等组成&#xff0c;B/S模式 Vscode管理前后端分离等等。 环境需要 1.运行环境&#xff1a;最好是Nodejs最新版&#xff0c;我…

matlab 的help没了

前两天还正常用&#xff0c;今天输入help 关键字 回复是没有相关的内容。 解决办法&#xff1a; 按照如下选择就行了 然后输入 help help 就会有显示了 help - Help for functions in Command Window This MATLAB function displays the help text for the functionalit…

大数据MapReduce学习案例:倒排索引

文章目录一&#xff0c;案例分析&#xff08;一&#xff09;倒排索引介绍&#xff08;二&#xff09;案例需求二&#xff0c;案例实施&#xff08;一&#xff09;准备数据文件&#xff08;1&#xff09;启动hadoop服务&#xff08;2&#xff09;虚拟机上创建文本文件&#xff0…

数据结构双向链表

双向链表也叫双链表&#xff0c;是链表的一种&#xff0c;它的每个数据结点中都有两个指针&#xff0c;分别指向直接后继和直接前驱。所以&#xff0c;从双向链表中的任意一个结点开始&#xff0c;都可以很方便地访问它的前驱结点和后继结点。一般我们都构造双向循环链表。 那…

WPF入门第三篇 ControlTemplate、Trigger与Storyboard

ControlTemplate、Trigger与Storyboard ControlTemplate通常用在Style中&#xff0c;Trigger通常作为ControlTemplate的一部分&#xff0c;StoryBoard表示动画效果&#xff0c;下面将通过对Button按钮设置这几项来简单说明这几项的用法。 在MainWindow中添加一个Button按钮&am…

Prometheus技术分享——如何监控宿主机和容器

这一期主要来跟大家聊一下&#xff0c;使用node_exporter工具来暴露主机和因公程序上的指标&#xff0c;利用prometheus来监控宿主机&#xff1b;以及通过通过Cadvisor监控docker容器。 一、部署node_exporter监控宿主机 1 下载软件包 wget https://github.com/prometheus/n…

分布式链路追踪SkyWalking

文章目录目录介绍服务端搭建注册中心启动注册中心修改持久化配置UI服务配置启动服务客户端搭建目录介绍 重要的目录结构分析如下&#xff1a; agent&#xff1a;客户端需要指定的目录&#xff0c;其中有一个jar&#xff0c;就是负责和客户端整合收集日志bin&#xff1a;服务端…

深入理解Linux网络技术内幕(十三)——协议处理函数

文章目录前言网络协议栈概论大蓝图Ethernet的链路层的选择&#xff08;LLC和SNAP&#xff09;网络协议栈的操作方式执行正确的协议处理函数特殊媒介封装协议处理函数的组织协议处理函数的注册Ethernet与IEEE 802.3帧设置封包类型设置Ethernet协议及长度逻辑链接控制&#xff08…

python+django球鞋商品竞拍卖网站vue

管理员功能模块 管理员登录&#xff0c;通过填写用户名、密码、角色等信息&#xff0c;输入完成后选择登录即可进入网上球鞋竞拍系统 管理员登录进入网上球鞋竞拍系统可以查看球鞋分类管理、热门竞拍管理、科比展区管理、用户管理、竞拍信息管理、消息通知管理、用户评价管理、…

单人脸的关键点检测

闲暇之余做了一个简单的单人的脸部关键点检测&#xff0c;使用的pytorch框架&#xff0c;别人训练好的现成模型。其中人脸检测模型是YOLOface5&#xff08;onnx格式的权重&#xff09;&#xff0c;关键点检测模型是PFLD&#xff08;能检测98个关键点&#xff09;&#xff0c;是…

计算机网络学习笔记(Ⅳ):网络层

目录 1 网络层内容 1.1 功能概述 1.任务 2.主要功能 1.2 数据交换方式 1.电路交换 2.报文交换 3.分组交换 4.方法对比 1.3 分组交换 1.数据报方式 2.虚电路方式 3.对比 2 路由算法与路由协议 2.1 路由算法 2.2 路由选择协议 3 IPv4 3.1 IP数据报格式 1.TCP/…