AOP概述
AOP(Aspect-Oriented Programming,面向切面的编程)是一种编程范式,专注于解耦业务逻辑和横切逻辑,从而达到提升内聚和模块化的目的。
业务逻辑 :处理业务的逻辑。
横切逻辑 :通常固定的出现在业务逻辑的边界处,在进入业务逻辑前或执行业务逻辑后做一些事情。
看一个例子:
横切逻辑
public class PerformanceMonitor {
public void start() {
System.out.println("开始时间: " + String.valueOf(System.currentTimeMillis()));
}
public void end() {
System.out.println("结束时间: " + String.valueOf(System.currentTimeMillis()));
}
}
业务逻辑
public class Biz {
private PerformanceMonitor pMonitor = new PerformanceMonitor();
public void doSomething() {
pMonitor.start();
System.out.println("做一些业务逻辑");
pMonitor.end();
}
public static void main(String [] args) {
Biz biz = new Biz();
biz.doSomething();
}
}
上面例子中,我们希望通过PerformanceMonitor
打印业务执行开始和结束时间,乍眼一看似乎没毛病。
那问题来了,如果我希望:
在调试阶段才打印开始和结束时间,应用发布后不打印。
希望在其他业务逻辑开始和结束的时候也打印时间。
按照现在的处理方式,业务逻辑和横切逻辑耦合在了一起,需要满足上述需求的话,需要修改代码后再重新编译,显然这种处理方式不够优美。
AOP就是一种优美的处理方式,如下:
Java AOP的实现方式
Java中实现AOP的方式分 静态AOP 和 动态AOP 两大类,下面分别列举。
静态AOP
在编译期间,横切逻辑直接以字节码形式编译到业务逻辑的字节码文件中,通常需要特殊的编译器。
Aspectj
Aspectj扩展了java语言,定义了AOP语法,所以它有一个专门的编译器(ajc)用来生成遵守Java字节码规范的Class文件
注意 : 此Aspectj,非Spring Aspectj。Spring Aspectj只是提供了和Aspectj AOP语法一致的语义注解,两者是完全不同的实现。
动态AOP
在运行期间,通过修改目标类的字节码、生成类的子类或代理类织入横切逻辑。
生成接口代理类(JDK动态代理)
运行时,通过为目标类实现的接口动态生成代理类,把横切逻辑织入到代理类中。
生成子类
运行时,通过为目标类生成子类,把横切逻辑织入到子类中。
自定义 ClassLoader(修改类)
运行时,在类加载器加载类的时候,修改目标类的字节码,把横切逻辑织入到目标类中。
ClassFileTransformer(修改类)
运行时,在Java Agent内通过Instrumentation转换类的字节码,把横切逻辑织入到目标类中。
AOP方式比较
AOP方式 | 效率 | 实现接口 | final method | 其他特点 | |
---|---|---|---|---|---|
Aspectj | 编译效率低,运行效率高 | 不需要 | 支持 | - | |
JDK动态代理 | 生成代理效率高,执行效率低 | 需要 | N/A | 通过反射方式调业务逻辑 | |
生成子类 | 生成子类效率低,执行效率高 | 不需要 | 不支持 | - | |
自定义 ClassLoader | 加载效率低,执行效率高 | 不需要 | 支持 | 只能对自动义类加载器加载的类织入 | |
ClassFileTransformer | 加载效率低,执行效率高 | 不需要 | 支持 | 对所有类织入 |
PS :未完待续,后续章节针对每一种AOP方式举例,实现PerformanceMonitor
横切逻辑的织入。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。