移动架构-AOP面向切面编程
AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。AOP是OOP的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生范型。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率
AOP切面编程的意义
当在使用面向对象编程的时候,会出现一种情况,这就是在多个类中如果需要统计某些信息,那么这些信息会出现在各个类中,但如果一旦需求改变,那么之前涉及到需求改动的地方都需要改动
这样的改动往往是巨大的,比如说在众多方法中需要统计代码段的执行时间,并打印出来,那么在需要统计的地方都需要添加相应的打印功能,然而如果现在要求将执行时间输入文件,那么每一个之前的类中都需要改写代码,这样的工作往往是很多的,这种做法也不符合设计模式的原则
把我们就需要某个方面的功能提出来与一批对象进行隔离,那么此时就有一种新的解决方案了,这便是AOP编程,AOP主要解决的问题包括:日志记录,性能统计,安全控制,事务处理,异常处理等
实例说明
使用OOP的编程思想,如果要输出一段代码执行前后的时间,那么因该是这么写的
public class MainActivity extends AppCompatActivity {
private static final String TAG = "cj5785";
private SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void onTestOne(View view) {
Log.d(TAG, "onTestOne: " + simpleDateFormat.format(new Date()));
long beagin = System.currentTimeMillis();
//代码逻辑
{
SystemClock.sleep(3000);
Log.d(TAG, "测试输出 1");
}
Log.d(TAG, "消耗时间: " + (System.currentTimeMillis() - beagin) + "ms");
}
public void onTestTwo(View view) {
Log.d(TAG, "onTestOne: " + simpleDateFormat.format(new Date()));
long beagin = System.currentTimeMillis();
//代码逻辑
{
SystemClock.sleep(3000);
Log.d(TAG, "测试输出 2");
}
Log.d(TAG, "消耗时间: " + (System.currentTimeMillis() - beagin) + "ms");
}
}
可以看出,如果每个类中都要求那么输出,这个工程量是巨大的,但如果这时候使用AOP,那么会省事很多
AOP编程的使用
AOP有其专有的编译工具,其是对javac的一个增强拓展编译器
Eclipse的使用:
下载aspectj,地址:http://www.eclipse.org/aspectj/downloads.php
下载aspectj的adt,地址:http://www.eclipse.org/ajdt/downloads/
安装,然后选择aspectj的编译器,把项目转换为aspectj项目
Android Studio的使用
在gradle添加如下,使项目使用aspectj编译
dependencies {
···
implementation 'org.aspectj:aspectjrt:1.8.13'
}
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 = 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
}
}
}
}
至于添加在modle的gradle中还是项目的gradle中就要看需求而定了
AOP实践
首先找到我们需要的切点
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface BehaviorTrace {
String value();
int type();
}
然后开始切
import android.util.Log;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import java.text.SimpleDateFormat;
import java.util.Date;
@Aspect
public class BehaviorAspect {
private static final String TAG = "cj5785";
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
//切点
@Pointcut("execution(@com.cj5785.aoptest.BehaviorTrace * *(..))")
public void annoBehavior() {
}
//切面
@Around("annoBehavior()")
public Object dealPoint(ProceedingJoinPoint point) throws Throwable {
//方法执行前
MethodSignature methodSignature = (MethodSignature) point.getSignature();
BehaviorTrace behaviorTrace = methodSignature.getMethod().getAnnotation(BehaviorTrace.class);
String contentType = behaviorTrace.value();
int type = behaviorTrace.type();
Log.d(TAG, contentType + "使用时间: " + simpleDateFormat.format(new Date()));
long beagin = System.currentTimeMillis();
//方法执行时
Object object = point.proceed();
//方法执行完成
Log.d(TAG, "消耗时间: " + (System.currentTimeMillis() - beagin) + "ms");
return object;
}
}
在需要切的地方做上标记
import android.os.SystemClock;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
public class MainActivity extends AppCompatActivity {
private static final String TAG = "cj5785";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
@BehaviorTrace(value = "onTestOne", type = 1)
public void onTestOne(View view) {
//代码逻辑
SystemClock.sleep(3000);
Log.d(TAG, "测试输出 1");
}
@BehaviorTrace(value = "onTestTwo", type = 2)
public void onTestTwo(View view) {
//代码逻辑
SystemClock.sleep(3000);
Log.d(TAG, "测试输出 2");
}
}
这样便完成了我们时间统计与具体业务的有效分离
移动架构-AOP面向切面编程的更多相关文章
- 【原创】Android AOP面向切面编程AspectJ
一.背景: 在项目开发中,对 App 客户端重构后,发现用于统计用户行为的友盟统计代码和用户行为日志记录代码分散在各业务模块中,比如在视频模块,要想实现对用户对监控点的实时预览和远程回放行为进行统计, ...
- 论AOP面向切面编程思想
原创: eleven 原文:https://mp.weixin.qq.com/s/8klfhCkagOxlF1R0qfZsgg [前言] AOP(Aspect-Oriented Programming ...
- 学习笔记: AOP面向切面编程和C#多种实现
AOP:面向切面编程 编程思想 OOP:一切皆对象,对象交互组成功能,功能叠加组成模块,模块叠加组成系统 类--砖头 系统--房子 类--细胞 系统--人 ...
- AOP 面向切面编程, Attribute在项目中的应用
一.AOP(面向切面编程)简介 在我们平时的开发中,我们一般都是面对对象编程,面向对象的特点是继承.多态和封装,我们的业务逻辑代码主要是写在这一个个的类中,但我们在实现业务的同时,难免也到多个重复的操 ...
- AOP面向切面编程的四种实现
一.AOP(面向切面编程)的四种实现分别为最原始的经典AOP.代理工厂bean(ProxyFacteryBean)和默认自动代理DefaultAdvisorAutoProxyCreator以及Bea ...
- Javascript aop(面向切面编程)之around(环绕)
Aop又叫面向切面编程,其中“通知”是切面的具体实现,分为before(前置通知).after(后置通知).around(环绕通知),用过spring的同学肯定对它非常熟悉,而在js中,AOP是一个被 ...
- Method Swizzling和AOP(面向切面编程)实践
Method Swizzling和AOP(面向切面编程)实践 参考: http://www.cocoachina.com/ios/20150120/10959.html 上一篇介绍了 Objectiv ...
- [转] AOP面向切面编程
AOP面向切面编程 AOP(Aspect-Oriented Programming,面向切面的编程),它是可以通过预编译方式和运行期动态代理实现在不修改源代码的情况下给程序动态统一添加功能的一种技术. ...
- C# AOP 面向切面编程之 调用拦截
有时候我们需要在代码中对方法调用进行拦截,并修改参数和返回值,这种操作叫做AOP(面向切面编程) 不过需要注意的是,AOP的效率很慢,在需要高效率场合慎用. 以下是C#的AOP方法: 首先建立一个控制 ...
随机推荐
- Greenplum 调优--查看子节点SQL运行状态
摘自<Greenplum企业应用实战> 重点: 使用gp_dist_random函数,将查询下发到每个Segement 创建查看子节点SQL运行状态视图 1)创建v_active_sql视 ...
- 块状链表 bzoj 3343教主的魔法
//块状链表//分块排序,然后每次查找时在暴力查找头和尾两个块.//中间那些块,因为有序所以只需2分查找即可.我用的是lower_pound();//插入是,也是头和尾暴力插入,中间那些加到一个累计里 ...
- QoS in RoCE (zz)
QoS in RoCE 首页分类标签留言关于订阅2018-03-22 | 分类 Network | 标签 RDMA RoCE ECN PFC Overview TCP/IP协议栈满足不了现代I ...
- 【原创】go语言学习(五)函数详解1
目录 1.函数介绍 2.多返回值和可变参数 3.defer语句 4.内置函数介绍 1.函数介绍 1.1定义: 有输⼊入.有输出,⽤用来执⾏行行⼀一个指定任务的代码块. func functionnam ...
- 二分算法题目训练(四)——Robin Hood详解
codeforces672D——Robin Hood详解 Robin Hood 问题描述(google翻译) 我们都知道罗宾汉令人印象深刻的故事.罗宾汉利用他的射箭技巧和他的智慧从富人那里偷钱,然后把 ...
- ROStopic 通信方式
操作演示,对 topic 通信方式的理解请看:点击打开链接 开启终端,运行 roscore 新开一个终端(已经安装好(ros-<distro>-ros-tutorials 包,否则运行 ...
- base/7/x86_64/filelists_db FAILED
解决办法: [root@localhost ~]# cd /var/lib/rpm [root@localhost rpm]# rm -rf __db.* # 清除原 rpmdb 文件 [root ...
- 实现Callable接口实现多线程
package com.roocon.thread.t2; import java.util.concurrent.Callable; import java.util.concurrent.Exec ...
- 【spark 算子案例】
package spark_example01; import java.io.File; import java.io.FileWriter; import java.io.IOException; ...
- C# 客户端网络请求 对HttpClient的封装
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明.本文链接:https://blog.csdn.net/a1037949156/article/d ...