面向切面,AOP,Aspect Oriented Programming。
一、示例
有这么一个类:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| public class UserServiceImpl implements UserService { @Override public void add() { System.out.println("...add..."); }
@Override public void del() { System.out.println("...del..."); }
@Override public void update() { System.out.println("...update..."); }
@Override public void query() { System.out.println("...query..."); } }
|
需求 1
要求在每一个方法执行前增加一步权限校验。
有一个笨办法可以解决,那就是将权限校验代码重复写到每个方法中。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| public class UserServiceImpl implements UserService { @Override public void add() { System.out.println("...权限校验..."); System.out.println("...add..."); }
@Override public void del() { System.out.println("...权限校验..."); System.out.println("...del..."); }
@Override public void update() { System.out.println("...权限校验..."); System.out.println("...update..."); }
@Override public void query() { System.out.println("...权限校验..."); System.out.println("...query..."); } }
|
需求 2
要求在每一个方法执行后增加一个日志记录功能,同时每一个方法之前的权限校验也需要做迭代。
这时候我们发现之前的做法是有问题的:
- 代码重复书写就意味的要重复修改
- 没有考虑到后续的扩展
于是我们想到了这样一个方法,将重复代码写到方法之后,并让原有方法调用,从而避免了维护的麻烦。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
| public class UserServiceImpl implements UserService { @Override public void add() { before(); System.out.println("...add..."); after(); }
@Override public void del() { before(); System.out.println("...del..."); after(); }
@Override public void update() { before(); System.out.println("...update..."); after(); }
@Override public void query() { before(); System.out.println("...query..."); after(); } public void before() { System.out.println("...权限校验2.0 ..."); } public void after() { System.out.println("...日志记录..."); } }
|
需求 2
要求对 XxxServiceImpl 等十余个类进行同样的改动。
这时候上面的方法也暴露出了它的局限性。
可以通过面向切面的方法来解决:
编写权限校验、日志记录等代码
1
| System.out.println("...权限校验2.0 ...");
|
1
| System.out.println("...日志记录...");
|
将这些代码以”某种方式”注入
通过预编译或动态代理实现
二、面向切面
1. 业务代码与增强代码
业务代码:直接用于实现需求的代码
增强代码:与需求实现无关的代码,额外的增强代码
例如:日志记录、性能统计、安全检查、权限校验等
2. 面向切面
所谓面向切面,就是通过“某种方式”在不改变原有代码的情况下,给程序添加特定功能。
典型的做法是:类专注于其业务代码,增强代码通过面向切面的方式注入。
3. 面向切面的作用
- 将增强代码与业务代码解耦
- 对象可以专注于其核心业务
- 通过配置的方式,使得增强代码仍然能够正常工作
- 相同代码被提取并重复运行,维护时也更加方便
参考