移动架构-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方法: 首先建立一个控制 ...
随机推荐
- guava字符串工具 Splitter 主要功能是拆分字符串为集合 Map
public class SplitterTest { public static void main(String args[]){ //1.拆分字符串为List集合 String str=&quo ...
- Codeforces Round #459 (Div. 2) C题【思维好题--括号匹配问题】
题意:给出一个串,只包含 ( ? ) 三种符号,求出有多少个子串是完美匹配的. ( ) ? ) => ( ) ( ) 完美匹配( ( ) ? => ( ( ) )完美匹配? ? ? ? = ...
- NodeJS后台
NodeJS后台 后台: 1.PHP 2.Java 3.Python 优势 1.性能 2.跟前台JS配合方便 3.NodeJS便于前端学习 https://nodejs.org/en/ 1.切换盘符 ...
- 关于.eslintrc.js代码检测的一些配置
配置参数 rules: { "规则名": [规则值, 规则配置] } 规则值: "off"或者0 //关闭规则关闭 "warn"或者1 / ...
- python eval的用法
>>>x = >>> eval( '3 * x' ) >>> eval('pow(2,2)') >>> eval('2 + 2' ...
- kvm 学习(二)镜像
Linux下 如何通过命令行使用现有的镜像创建.启动kvm虚拟机 这里假定已经创建好了相应的镜像: eg:我这里制作的镜像名称为zu1-centos7.img # ls zu1-centos7.img ...
- mysql5.7 源码安装步骤
操作系统:centos 7 mysql版本:5.7 下载地址:https://dev.mysql.com/get/Downloads/MySQL-5.7/mysql-5.7.24-linux-gli ...
- mapred-site.xml 基本配置参考
说明:这是hadoop2.x版本的参数.下面的value都是参数默认值. 常用配置: ♥♥♥ .mapreduce.job.hdfs-servers value:${fs.defaultFS} 说明: ...
- Nginx之URL重写(rewrite)配置
Nginx URL重写(rewrite)配置及信息详解1)if判断指令 语法为if(condition){…} #对给定的条件condition进行判断.如果为真,大括号内的rewrite指令 ...
- Jenkins部署maven项目到远端服务器
jenkins服务器地址:192.168.1.203 项目部署机器地址:192.168.1.201,192.168.1.200 代码托管github 虽然比较low,但是入门是可以的! Jenkins ...