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中的使用所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)