一、AOP 的基本概念
1.1 什么是 AOP
Aspect Oriented Programming,面向切面编程。
就跟我们说 OOP 是面向对象一样,AOP 是面向切面的。切面是分散在应用中的一个标准代码或功能。切面通常与实际的业务逻辑不同(例如,事务管理)。每个切面专注于一个特定的环切功能。
这里的切面呢,可以理解为横切。比如在所有的 DAO 层方法上加上一个同样的切面,功能是记录日志;又或者在某个接口上应用一个切面,作用是检查权限。
AOP 是基于代理来实现的。而代理又分为静态代理和动态代理。两者的区别在于代理类于何时生成。
下面我们讲讲代理是怎么回事?
1.2 代理与 Spring AOP
代理分为静态代理和动态代理:
- 静态代理:代理类在编译阶段生成,程序运行前就存在。包括:AspectJ 静态代理、JDK 静态代理
- 动态代理:代理类在程序运行时创建。包括:JDK 动态代理、CGLib 动态代理
Spring AOP 原理:
- JDK Proxy:interface based
- CGLib Proxy: class based
Spring AOP 中默认使用 JDK 动态代理,通过反射获取被代理的类,这个类必须实现一个接口。如果目标类没有实现接口,就会默认使用 CGLIB Proxy 来动态生成代理目标类,后者是被代理类的子类。
可以通过获取代理对象并打印的方式来查看其类型(JDK Proxy 下是 com.sun.prxy, CGlib 下是子类.
AspectJ: 用特定的编译器和语法,在编译时增强,实现了静态代理技术。
1.3 Spring AOP 与 AspectJ 的区别
AspectJ 是一套完整的 AOP 解决方案,而 Spring AOP 并不是 —— 它只是在 Spring 框架下满足其使用要求的一个解决方法,比如 Spring AOP 仅支持对方法使用切面。
二、静态代理
2.1 AspectJ 静态代理
基于特殊的编译器和语法。这里不多介绍了。
IDEA 下编译 AspectJ 可以参考这篇:https://blog.gaodaima.com/gavin_john/article/details/80156963
2.2 JDK 静态代理
实际上是利用实现一个具体的代理类来调用业务类。代理类持有了一个业务类的引用。
更概况地说,JDK 静态代理体现的是一种设计模式。
缺点很明显,代码冗余,难以维护。
这里以 借书 和 还书 这两个行为来作为一个示例:
编写一个 BookService 接口:
public interface BookService {  <b>本文来源gao@!dai!ma.com搞$$代^@码5网@</b>;boolean borrow(String id, String userName); boolean reBack(String id, String userName); }
然后实现这个接口:
public class BookServiceImpl implements BookService { @Override public boolean borrow(String id, String userName) { System.out.println(userName + " 借书:" + id); return true; } @Override public boolean reBack(String id, String userName) { System.out.println(userName + " 还书:" + id); return true; } }