动态代理,AOP和Spring

笔记

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方法(因为原理是继承)。

posted @ 2020-02-06 20:25  带了1个小才艺  阅读(125)  评论(0编辑  收藏  举报