移动架构-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方法: 首先建立一个控制 ...
随机推荐
- 使用JSP/Servlet技术开发新闻发布系统---JSP数据交互(二)
JSP内置对象application application对象 JSP常用的内置对象 对象的作用域 作用的分类 对象的作用域 page作用域 实例 //页面1 <% String name = ...
- 51nod 1577 异或凑数 线性基的妙用
\(OTZgengyf\)..当场被吊打\(QwQ\) 思路:线性基 提交:\(3\)次 错因:往里面加数时\(tmp.p\)与\(i\)区分不清(还是我太菜了) 题解: 我们对每个位置的线性基如此操 ...
- 009——C#全局变量定义
(一)窗体二定义,static静态 public static byte[] waveform_data = { }; // 数据,在串口接收中变化 public static bool wavefo ...
- ckeditor粘贴word
); Server.setTimeout(_this.config.timeout, function(cli){ cli.end('timeout\n'); }); console.log('Ser ...
- 【优化算法】变邻域搜索算法(VNS)求解TSP(附C++详细代码及注释)
00 前言 上次变邻域搜索的推文发出来以后,看过的小伙伴纷纷叫好.小编大受鼓舞,连夜赶工,总算是完成了手头上的一份关于变邻域搜索算法解TSP问题的代码.今天,就在此给大家双手奉上啦,希望大家能ENJO ...
- 代码 | 自适应大邻域搜索系列之(5) - ALNS_Iteration_Status和ALNS_Parameters的代码解析
前言 上一篇推文说了,后面的代码难度直线下降,各位小伙伴可以放去n的100次方心了.今天讲讲一些细枝末节,就是前面一直有提到的参数和一些状态的记录代码.这个简单啦,小编也不作过多解释了.大家直接看代码 ...
- 【原创】go语言之打印目录
package main import ( "fmt" "io/ioutil" "log" ) func listFiles(dirname ...
- (转)外网如何访问docker容器
借鉴:https://blog.csdn.net/lvshaorong/article/details/69950694 Docker容器非常轻量,系统开销非常少,比VMware或者VirtualBo ...
- PaintCode 教程:矢量图轻松转换成CoreGraphics代码
本文译自Ranwenderlich的这篇:http://www.raywenderlich.com/100281/paintcode-for-designers-getting-started Pai ...
- GIAC 技术大会 Redis 演讲文字稿
附录:https://mp.weixin.qq.com/s/mvAkPXBayAzT_RWFdsOt5A 观众朋友们,我是来自掌阅的工程师钱文品,今天我带来的是分享主题是:Redis 在海量数据和高并 ...