定义
代理模式是一种结构型设计模式, 让你能够提供对象的替代品。 代理控制着对原对象的访问, 并允许在将请求提交给对象前后进行一些处理。
静态代理
这种代理方式需要代理对象和目标对象实现一样的接口。优点:可以在不修改目标对象的前提下扩展目标对象的功能。缺点:扩展被代理类功能时会产生过多的代理类,如果目标接口修改,所有类包括代理类都要修改。
静态代理的两种实现方式:1、继承,2、组合
先定义目标类和接口如下:
1 | public interface Flyable { |
继承
通过继承的方式来新建两个代理类统计时间和记录Log,
1 | public class BirdFlyTime extends Bird { |
使用继承代理:可知使用继承实现的静态代理,不能同时使用
1 | public static void main(String[] args) { |
组合
通过组合的方式来新建两个代理类统计时间和记录Log,
1 | public class BirdFlyTimeProxy implements Flyable { |
使用组合代理:可知使用组合实现的静态代理可以同时使用并灵活调换代理的执行顺序
1 | public static void main(String[] args) { |
动态代理
相对于静态代理需要手动书写代理类然后编译生成class文件载入JVM运行,动态代理是在JVM运行起来以后在内存中动态的创建代理类class文件(字节流)并载入JVM执行。
动态代理又分为JDK动态代理和CGLIB动态代理。
JDK动态代理
要使用JDK动态代理有一个前提,要求被代理的目标类必须实现接口。JDK动态代理可以看作组合型静态代理的扩展,它封装了具体的被代理目标类,提供一个统一的接口InvocationHandler,让代理类实现这个接口即可,实现了对所有不同目标类的代理功能。
还是以上面Flyable接口+Bird类举例使用JDK代理。
首先代理类需要实现InvocationHandler接口
1 | public class BirdLogProxy implements InvocationHandler { |
然后根具体的目标类绑定,调用Proxy.newProxyInstance即可生成代理类
1 | public class JDKProxyUsage { |
CGLIB动态代理
CGLIB是一个第三方代码生成类库,它的底层是通过使用一个字节码处理框架ASM,来转换字节码并生成新的类。CGLIB动态代理和JDK动态代理的区别是:CGLIB对被代理的目标类没有必须要实现接口的要求,只要目标类不是final类即可,由此可见CGLIB是使用继承的方式来实现代理类的。
还是以上面Flyable接口+Bird类举例使用CGLIB代理。
首先代理类需要实现MethodInterceptor接口(此处使用了单例模式),通过getProxy方法即可生成代理类
1 | public class BirdLogProxy implements MethodInterceptor{ |
使用CGLIB代理如下
1 | public static void main(String[] args) { |