编程思想 面向切面(AOP)

面向切面,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. 面向切面的作用

  • 将增强代码与业务代码解耦
  • 对象可以专注于其核心业务
  • 通过配置的方式,使得增强代码仍然能够正常工作
  • 相同代码被提取并重复运行,维护时也更加方便

参考