笔记
1. 什么是AOP?
Aspect-Oriented Programming 面向切面编程,关注一个统一的切面,相对于OOP(面向对象编程)。
适合的场景:
- 日志
- 缓存
- 鉴权
如果用OOP来做怎么办?
- 装饰器模式
2. 装饰器模式 (OOP, 静态代理)
Decorator pattern:
动态地为一个对象增加功能,但是不改其结构。
public interface DataService {
String a(int i);
String b(int i);
}
public class DataServiceImpl implements DataService {
@Override
public String a(int i) {
return UUID.randomUUID().toString();
}
@Override
public String b(int i) {
return UUID.randomUUID().toString();
}
}
public class Main {
static DataService service = new CacheDecorator(new LogDecorator(new DataServiceImpl()));
public static void main(String[] args) {
System.out.println(service.a(1));
System.out.println(service.b(1));
}
}
假如是class,就会有浪费。
3. AOP动态代理
public class LogProxy implements InvocationHandler {
private DataService delegate;
public LogProxy(DataService delegate) {
this.delegate = delegate;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println(method.getName() + " is invoker " + Arrays.toString(args));
Object result = method.invoke(delegate, args);
System.out.println(method.getName() + " is finished: " + result);
return result;
}
}
public class Main {
static DataService service = new DataServiceImpl();
public static void main(String[] args) {
DataService dataService = (DataService) Proxy.newProxyInstance(
service.getClass().getClassLoader(),
new Class[]{DataService.class},
new LogProxy(service));
dataService.a(1);
dataService.b(3);
}
}
优点:方便,不需要依赖任何第三方库
缺点:功能受限,只能用于接口 (源代码中接收参数为interface,如果是class会报异常)
4. 如果是class怎么办?
CGLIB/ByteBuddy字节码生成
public class Main {
static DataServiceImpl service = new DataServiceImpl();
public static class LogInterceptor implements MethodInterceptor {
private DataServiceImpl delegate;
public LogInterceptor(DataServiceImpl delegate) {
this.delegate = delegate;
}
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println(method.getName() + " is invoker " + Arrays.toString(objects));
Object result = method.invoke(delegate, objects);
System.out.println(method.getName() + " is finished: " + result);
return result;
}
}
public static void main(String[] args) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(DataServiceImpl.class);
enhancer.setCallback(new LogInterceptor(service));
DataServiceImpl enhancedService = (DataServiceImpl) enhancer.create();
enhancedService.a(1);
enhancedService.b(2);
}
// 这里会动态生成一个叫做DataServiceImpl$$EnhancerByCGLIB$$9bce1175@651的类,它是动态生成出来,并且是继承我们的DataServiceImpl的。
优点:强大,不受接口的限制
缺点:需要额外引用第三方库,不能增强final类/final/private方法(因为原理是继承)。