ZB-046-01AOP和装饰器模式

AOP和动态代理

什么是AOP Aspect-Oriented Programming

  • 相对于OOP
  • AOP是面向切片编程,关注一个统一的切面
  • AOP和Spring是不同的东西
    • 为什么考Spring总是问 AOP,因为绝大多数使用AOP的场景是在 spring容器里

OOP

1
2
3
4
5
6
a.b()
b.c()

假如我现在有个 AService 它有100个方法,如何做到调用它的每个方法的时候打印日志,结束的时候打印日志呢?

装饰器模式

AOP

1
2
3
4
5
6
7
8
9
10
11
AService 它有100个方法
AService
----|a()
----|b()
----|c()
----|d()
----|...
----|xxx()

在进入每个方法的瞬间都看作一个切面 ,每次进入这个方法的一瞬间拦截下来执行某些操作
关注的不是对象方法本身,而是在进入某个方法的一瞬间的这个切面

AOP适用于那些场景

  • 需要统一处理的场景
    • 日志
    • 缓存
    • 鉴权
  • 如果用OOP来做需要怎么办?
    • 装饰器模式

装饰器模式

  • 俄罗斯套娃
  • 在它外面包一层

新建 maven空项目

DataService.java

1
2
3
4
public interface DataService {
String a(int i);
String b(int i);
}

DataServiceImpl.java

1
2
3
4
5
6
7
8
9
10
public class DataServiceImpl implements DataService {

public String a(int i) {
return UUID.randomUUID().toString();
}

public String b(int i) {
return UUID.randomUUID().toString();
}
}

Main.java

1
2
3
4
5
6
7
8
9
10
package com.aop.demo;

public class Main {
static DataService service = new DataServiceImpl();

public static void main(String[] args) {
System.out.println(service.a(1));
System.out.println(service.b(1));
}
}

需求在DataService的任何一个方法进入的时候打印日志

你可能会这样~~~

  • 但是如果它有100个方法,你就要写100次非常容器出错
1
2
3
4
5
6
7
8
9
10
11
12
13
public class DataServiceImpl implements DataService {
public String a(int i) {
System.out.println("a is start");
System.out.println("a is finish");
return UUID.randomUUID().toString();
}

public String b(int i) {
System.out.println("b is start");
System.out.println("b is finish");
return UUID.randomUUID().toString();
}
}

装饰器模式

  • 动态为对象增加功能,但是不改变其结构
  • 本质是一个“包装”

新建 LogDecorator.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public class LogDecorator implements DataService {
DataService delegate;

public LogDecorator(DataService delegate) {
this.delegate = delegate;
}

public String a(int i) {
System.out.println("a is start");
String value = delegate.a(i);
System.out.println("a is finish");
return value;
}

public String b(int i) {
System.out.println("b is start");
String value = delegate.a(i);
System.out.println("b is finish");
return value;
}
}

Main.java

1
2
3
4
5
6
7
8
9
public class Main {
// 额外包了一层,不用改变原有功能
static DataService service = new LogDecorator(new DataServiceImpl());

public static void main(String[] args) {
System.out.println(service.a(1));
System.out.println(service.b(1));
}
}

带缓存功能的装饰器

CacheDecorator.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public class CacheDecorator implements DataService {
private Map<String,String> cache = new HashMap();

private DataService delegate;

public CacheDecorator(DataService delegate) {
this.delegate = delegate;
}

public String a(int i) {
String cacheValue = cache.get("a");
if(cacheValue == null){
String realValue = delegate.a(i);
cache.put("a",realValue);
return realValue;
} else {
return cacheValue;
}
}

public String b(int i) {
return null;
}
}

代码链接

https://github.com/slTrust/java-aop-demo