框架:AspectJ
AOP虽然是方法论,但就好像OOP中的Java一样,一些先行者也开发了一套语言来支持AOP。目前用得比较火的就是AspectJ了,它是一种几乎和Java完全一样的语言,而且完全兼容Java(AspectJ应该就是一种扩展Java,但它不是像Groovy[1]那样的拓展。)。当然,除了使用AspectJ特殊的语言外,AspectJ还支持原生的Java,只要加上对应的AspectJ注解就好。所以,使用AspectJ有两种方法:
- 完全使用AspectJ的语言。这语言一点也不难,和Java几乎一样,也能在AspectJ中调用Java的任何类库。AspectJ只是多了一些关键词罢了。
- 或者使用纯Java语言开发,然后使用AspectJ注解,简称@AspectJ。
AspectJ的配置可以参考另一篇文章Android中使用AspectJ
Join Points介绍
Join Points是AspectJ中的一个关键概念。Join Points可以看作是程序运行时的一个执行点,比如:一个函数的调用可以看作是个Join Points,如Log.e()这个函数,e()可以看作是个Join Points,而调运e()的函数也可以认为是一个Join Points;设置一个变量,或者读取一个变量也可以是个Join Points;for循环也可以看作是Join Points。
理论上说,一个程序中很多地方都可以被看做是Join Points,但是AspectJ中,只有下面所示的几种执行点被认为是Join Points:
Join Points | 说明 | 示例 |
---|---|---|
method call | 函数调用 | 比如调用Log.e(),这是一处JPoint |
method execution | 函数执行 | 比如Log.e()的执行内部,是一处Join Points。注意它和method call的区别。method call是调用某个函数的地方。而execution是某个函数执行的内部。 |
constructor call | 构造函数调用 | 和method call类似 |
constructor execution | 构造函数执行 | 和method execution类似 |
field get | 获取某个变量 | 比如读取DemoActivity.debug成员 |
field set | 设置某个变量 | 比如设置DemoActivity.debug成员 |
pre-initialization | Object在构造函数中做得一些工作。 | |
initialization | Object在构造函数中做得工作 | |
static initialization | 类初始化 | 比如类的static{} |
handler | 异常处理 | 比如try catch(xxx)中,对应catch内的执行 |
advice execution | 这个是AspectJ的内容,稍后再说 |
这里列出了AspectJ所认可的JoinPoints的类型。实际上,也就是你想把新的代码插在程序的哪个地方,是插在构造方法中,还是插在某个方法调用前,或者是插在某个方法中,这个地方就是Join Points,当然,不是所有地方都能给你插的,只有能插的地方,才叫Join Points。
Pointcuts介绍
一个程序会有多个Join Points,即使同一个函数,也还分为call和execution类型的Join Points,但并不是所有的Join Points都是我们关心的,Pointcuts就是提供一种使得开发者能够选择自己需要的JoinPoints的方法。
Advice
Advice就是我们插入的代码以何种方式插入,有Before还有After、Around。
看个例子
@Before("execution(* android.app.Activity.on**(..))")
public void onActivityMethodBefore(JoinPoint joinPoint) throws Throwable {
}
这里会分成几个部分,我们依次来看:
- @Before:Advice,也就是具体的插入点
- execution:处理Join Point的类型,例如call、execution
- (* android.app.Activity.on**(..)):这个是最重要的表达式,第一个*表示返回值,*表示返回值为任意类型,后面这个就是典型的包名路径,其中可以包含 * 来进行通配,几个 * 没区别。同时,这里可以通过&&、||、!来进行条件组合。()代表这个方法的参数,你可以指定类型,例如android.os.Bundle,或者(..)这样来代表任意类型、任意个数的参数。
- public void onActivityMethodBefore:实际切入的代码。
Before和After其实还是很好理解的,也就是在Pointcuts之前和之后,插入代码,那么Around呢,从字面含义上来讲,也就是在方法前后各插入代码,是的,他包含了Before和After的全部功能,代码如下:
@Around("execution(* com.xys.aspectjxdemo.MainActivity.testAOP())")
public void onActivityMethodAround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {String key = proceedingJoinPoint.getSignature().toString();Log.d(TAG, "onActivityMethodAroundFirst: " + key);proceedingJoinPoint.proceed();Log.d(TAG, "onActivityMethodAroundSecond: " + key);
}
其中,proceedingJoinPoint.proceed()代表执行原始的方法,在这之前、之后,都可以进行各种逻辑处理。
自定义Pointcuts(注解形式)
自定义Pointcuts可以让我们更加精确的切入一个或多个指定的切入点。
首先我们要定义一个注解类
@Retention(RetentionPolicy.CLASS)
@Target({ElementType.CONSTRUCTOR, ElementType.METHOD})
public @interface DebugTrace {
}
在需要插入代码的地方加入这个注解。如在MainActivity中加入,
public class MainActivity extends AppCompatActivity {final String TAG = MainActivity.class.getSimpleName();@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);logTest();}@DebugTracepublic void logTest() {Log.e(TAG, "log test");}
}
最后,创建切入代码
@Pointcut("execution(@com.kun.aspectjtest.aspect.DebugTrace * *..*.*(..))")
public void DebugTraceMethod() {}@Before("DebugTraceMethod()")
public void beforeDebugTraceMethod(JoinPoint joinPoint) throws Throwable {String key = joinPoint.getSignature().toString();Log.e(TAG, "beforeDebugTraceMethod: " + key);
}
log如下
在AspectJ的切入点表达式中,我们前面都是使用的execution,实际上,还有一种类型——call,那么这两种语法有什么区别呢,对于Call来说:
Call(Before)
Pointcut{Pointcut Method
}
Call(After)
对于Execution来说:
Pointcut{execution(Before)Pointcut Methodexecution(After)
}
withincode
这个语法通常来进行一些切入点条件的过滤,作更加精确的切入控制。如下
public class MainActivity extends AppCompatActivity {final String TAG = MainActivity.class.getSimpleName();@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);aspectJ1();aspectJ2();aspectJ3();}public void aspectJTest() {Log.e(TAG, "execute aspectJTest");}public void aspectJ1(){aspectJTest();}public void aspectJ2(){aspectJTest();}public void aspectJ3(){aspectJTest();}
}
aspectJ1(),aspectJ2(),aspectJ3()都调用了aspectJTest方法,但只想在aspectJ2调用aspectJTest时插入代码,这个时候就需要使用到Pointcut和withincode组合的方式,来精确定位切入点。
@Pointcut("(call(* *..aspectJTest()))&&withincode(* *..aspectJ2())")
public void invokeAspectJTestInAspectJ2() {
}@Before("invokeAspectJTestInAspectJ2()")
public void beforeInvokeaspectJTestInAspectJ2(JoinPoint joinPoint) throws Throwable {Log.e(TAG, "method:" + getMethodName(joinPoint).getName());
}private MethodSignature getMethodName(JoinPoint joinPoint) {if (joinPoint == null) return null;return (MethodSignature) joinPoint.getSignature();
}
log如下
04-02 23:44:40.681 12107-12107/ E/MainActivity: execute aspectJTest
04-02 23:44:40.681 12107-12107/ E/AspectTest: method:aspectJTest
04-02 23:44:40.681 12107-12107/ E/MainActivity: execute aspectJTest
04-02 23:44:40.681 12107-12107/ E/MainActivity: execute aspectJTest
以上就是Aspecj的基本使用方法
框架:AspectJ相关推荐
- Spring的AOP思想和实现AOP思想的框架AspectJ
章节目标:详细解释什么是Spring AOP思想和对于该思想实现的AspectJ框架的实现用法. 一.AOP面向切面编程 1.AOP概述 AOP(Aspect Orient Programming)面 ...
- Spring5框架—— AspectJ
目录 一.操作术语 二.AspectJ(准备工作) 1.什么是 AspectJ 2.基于AspectJ 实现AOP操作 3.切入点表达式 三.AOP操作(AspectJ注解) 四.AOP操作(Aspe ...
- aopaspect区别_面试官:什么是AOP?Spring AOP和AspectJ的区别是什么?
AOP(Aspect Orient Programming),它是面向对象编程的一种补充,主要应用于处理一些具有横切性质的系统级服务,如日志收集.事务管理.安全检查.缓存.对象池管理等. AOP实现的 ...
- Aspectj 实现Method条件运行
最近我花了半个小时实现了一个Method的按自定义条件运行的plugin,Condition-Run .实现场景是由于我所工作的客户经常会是在同一个代码集上实现多个Brand,所以有些功能只会限制是几 ...
- 2020最新Spring框架教程【IDEA版】-Spring框架从入门到精通
第一章:认识Spring spring思维导图 01p/102p Spring认识框架 02p/102p Spring官网浏览以及资源介绍 03p/102p 框架内部模块 第二章 IoC控制反转 04 ...
- 关于spring框架,看这一篇就够了~~~
文章目录 一.Spring是什么? 1. Spring定义 2. Spring的优点 3. Spring的核心结构 4. Spring的核心思想 4.1 IOC和DI 4.2 AOP 二.IOC和AO ...
- 设计模式_spring框架中常用的8种设计模式
spring框架中常用到的8种设计模式清单如下: 设计模式 使用地方 备注 工厂模式 BeanFactory ApplicationContext 单例模式 Spring中的Bean 代理模式 Spr ...
- Spring框架中的核心技术之AOP
目录 1. 什么是AOP? 2. 实现AOP技术的框架有哪些? 2.1 Spring框架中的AOP技术 2.2 Aspectj框架 2.3 小结 3. Aspectj框架中的使用AOP的方式 4. A ...
- Spring 5.X系列教程:满足你对Spring5的一切想象-持续更新
文章目录 简介 Spring基础 Core核心技术 Testing测试 Data Access Web Servlet Web Reactive 总结 简介 是什么让java世界变得更好,程序员变得更 ...
- spring5高级编程_Spring 5.X系列教程:满足你对Spring5的一切想象-持续更新
简介 是什么让java世界变得更好,程序员变得更友爱,秃头率变得不是那么的高,让程序员不必再每天996,有时间找个女朋友? 是Spring. 是什么让企业级java应用变得简单易懂,降低了java程序 ...
最新文章
- Python零基础入门(2)——常用的快捷命令、数据类型、输入输出格式、变量介绍
- 基于SSH框架实际开发时遇到的问题及解决办法
- 转载sunboy_2050 - Android APK反编译详解(附图)
- OpenStack虚机网卡的创建过程
- 洛谷P1372 又是毕业季IP1414 又是毕业季II[最大公约数]
- Android中自定义属性(attrs.xml,TypedArray的使用)
- Winform中实现实时颜色拾取器显示RGB和16进制颜色(附代码下载)
- 【Docker从入门到精通_1】Ubuntu16.04版本安装与配置
- Docker构建Spark镜像手动执行命令示例
- linux之网络编程ICMP校验算法
- 任务管理平台_jytask一个任务调度统一管理平台
- 指数随机变量 泊松过程跳_概率微课:第二章(19) 连续型随机变量函数的分布1...
- linux 14.04安装qt5.9,Ubuntu20.04安装Qt5.9.9+Qt creator
- 【转】Python 2.x和Python3.x的区别
- 【校内模拟】2048
- 供应链SCOR模型搭建/改进
- UDS诊断系列介绍03-DCM
- 蒸汽管道图纸符号_管道图形符号
- Centos7.8下Nmap的安装与使用
- CES 2022:四大芯片巨头正面厮杀,抢滩自动驾驶、元宇宙
热门文章
- Android深度探索第五章
- jenkins调整jdk版本不生效的解决办法
- [python-图像处理]python图片处理技巧[基本操作]
- 求解最长单调递增子串
- 为提高绩效,HR需要做的改进工作
- IO模型(select, poll, epoll的区别和原理)
- Linux内核目录结构(2.6版本以上的kernel)
- MongoDB和Redis区别
- SSD+HDD双硬盘+MSI主板win8.1+ubuntu17.04双系统安装总结
- 基于Android Studio的内存泄漏检测与解决全攻略