移动架构-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方法: 首先建立一个控制 ...
随机推荐
- 51nod 1565 模糊搜索 FFT
这...好强啊\(QwQ\) 思路:卷积?\(FFT\)? 提交:\(5\)次 错因:一开始的预处理写错了(竟然只错了最后几个大点)闹得我以为\(FFT\)写挂了\(QwQ\) 题解: 对四种字符分开 ...
- greenplum(postgresql) 数据字典
greenplum是基于postgresql开发的分布式数据库,里面大部分的数据字典是一样的.我们在维护gp的时候对gp的数据字典比较熟悉,特此分享给大家.在这里不会详细介绍每个字典的内容,只会介绍常 ...
- qsing
qsing1 1.低仿机器人 一道大模拟 2.放爆竹 小辉原本想让小明告诉他,如果同时点燃n串雷,最多会有多长的时间至少有两串雷爆炸的声音是一样的. 但是小辉觉得这个问题真是太简单了,所以决定问小明, ...
- 比Excel还简单的SQL语句查询
大家好,我是jacky朱元禄,很高兴继续跟大家分享<MySQL数据分析实战>系列课程,前面的课程jacky分享了数据层面增删改查中的增删改,下面的课程我们要说增删改查的这个查,jacky说 ...
- Linux下基于Xampp的TestLink的安装部署
由于项目需要,故需要搭建Testlink,且出于稳定,考虑在linux环境部署,当然windows系统也是可以的. 系统:64位操作系统 linux:centos6.8 testlink:1.9.14 ...
- Java枚举抽象方法实战
需求背景 需求已经确定了几个固定的常量值,并且每个常量值都有相同的行为,但是具体实现细节不同.建议使用枚举抽象方法,优点:结构清晰,便于扩展. 枚举类实现抽象方法 与常规抽象类一样,enum类允许我们 ...
- 跑shell脚本出错问题以及解决。
脚本信息: #!/bin/bash function hello(){ cat <<YJT echo "hello world!!!" YJT } hello 错误: ...
- sftp远程传输脚本
该脚本主要是是批量修改文件名,然后传输文件到服务器#!/bin/bash #脚本名:sftp.sh while true do num=`cat test.txt|wc -l` ;a<=$num ...
- Tkinter 之Label标签
一.参数说明 语法 作用 Label(window,text=‘xxxxx’) 需要在界面显示的Label标签内容 Label(window,text=‘xxxxx’,height=2) 组件的高度( ...
- Linux中split大文件分割和cat合并文件
当需要将较大的数据上传到服务器,或从服务器下载较大的日志文件时,往往会因为网络或其它原因而导致传输中断而不得不重新传输.这种情况下,可以先将大文件分割成小文件后分批传输,传完后再合并文件. 1.分割 ...