java静态代理、动态代理、装饰设计模式

一、代理描述
在不修改源码的情况下,增强方法,在方法执行前后做任何你想做的事情。如:记录日志、权限控制等。
一旦某个实例被代理后,则应使用代理后的对象进行方法调用,而非被代理的对象。此时使用者应该忽略被代理的对象,只关注代理后的对象。
代理的方式有:静态代理、动态代理。

二、静态代理
代理对象的类是真实存在的,并非动态生成的。
代理对象持有被代理对象的引用,可以不实现任何接口。
代理对象中的方法通过被代理对象的引用调用被代理对象的方法,同时执行代理逻辑。

三、JDK动态代理使用方法
1、被代理对象实现某些接口(必要条件)。
2、编写InvocationHandler子类,实现invoke方法。
在invoke方法中通过反射机制调用被代理对象的业务方法,同时,在该方法中实现代理需要做的逻辑。
3、使用Proxy.newProxyInstance创建代理后的对象。
4、通过代理后的对象,调用业务方法。

四、动态代理解读
代理对象持有InvocationHandler的引用,每当通过代理对象调用业务方法时会调用InvocationHandler的invoke方法。
在InvocationHandler的invoke方法中通过反射机制调用被代理对象对应的业务方法,同时执行代理逻辑。
Invoke方法中第一个参数: Object proxy,该对象是代理后的对象。在invoke方法中使用该对象时需小心,防止出现java.lang.StackOverflowError异常。
JDK的动态代理依靠接口实现,如果有些类并没有实现接口,则不能使用JDK代理,这就要使用cglib动态代理了。
cglib的原理是对指定的目标类生成一个子类,并覆盖其中方法实现代理,但因为采用的是继承,所以不能对final修饰的类或方法进行代理。

五、动态代理解读
模拟Proxy.newProxyInstance创建的代理对象步骤(代码见附件Proxy.java):
1、 根据被代理对象的接口信息,通过Java反射机制动态生成代理类的字符串。该代理类也同样实现这些接口中的方法。
1.1、在方法的实现中调用InvocationHandler的invoke方法,将当前对象、方法信息、入参传递过去。
2、根据创建好的代理类字符串,创建Java文件。
3、编译该Java文件,生成代理类字节码。
4、通过被代理类的加载器,将编译好的代理类字节码加载类到内存。
5、创建代理对象的实例。

六、静态代理与动态代理区别
静态代理通常只代理一个类,动态代理可以代理任何接口的实现类。
静态代理事先知道要代理的是什么,而动态代理不知道要代理什么东西,只有在运行时才知道。
静态代理在程序运行前代理类的.class文件就已经存在了,动态代理是程序运行时动态生成。

七、装饰设计模式
装饰设计模式是静态代理的特殊模式。静态代理中,代理对象和被代理对象实现同样的接口,这种设计模式为装饰设计模式。
装饰设计模式与代理设计模式对比:
1、装饰对象与被装饰对象都实现同样的接口,代理对象和被代理对象也同样需要实现同样的接口。
2、创建装饰对象时需调用有参构造函数,传入被装饰对象;创建代理对象时,在内部自行创建被代理对象。
3、主要区别还得从语义上区分。装饰起到方法增强效果,代理不仅起到方法增强效果,还起到权限控制效果。
4、装饰设计模式是静态代理的一种。

猜你喜欢

转载自871656094.iteye.com/blog/2355335