Java动态代理
2020-06-29 04:26
225 查看
代理模式
代理模式就是代理对象完成用户的请求,屏蔽用户对真是对象的访问。
打个比方,在早些年间我们要买电脑,都是直接跟电脑生产厂家进行交易,我们付款给生产厂家,然后厂家发货给我们。随着生产厂家的业务发展,用户越来越多,对商品的销售和售后需要付出更多的财力和物力。这时,一些人洞察了这一机遇,就搞了了一个叫代理商/经销商的东西出来,如某宝,某东。后来,我们如果再想买电脑,就不是直接跟电脑厂家交易了,而是代理商跟生产厂家进行联系,我们再跟代理商进行交易。对商品的售后,也不再是买家跟厂家进行联系了,而是买家跟代理商联系了。对于买家而言,这个中间商就是对生产厂家进行了代理。
静态代理
要说动态代理,有必要先了解下静态代理,静态代理和动态代理的主要区别前者的代理类需要程序员手动编码,而后者的代理类是自动生成的。
代码实现
- 创建IProducer接口,定义销售商品规范
public interface IProducer { /** * 销售商品 * @param maney */ void sale(float maney); }
- 创建Producer类,定义生产厂家
public class Producer implements IProducer { public void sale(float maney) { System.out.println("销售了商品,并拿到了钱:"+maney); } }
- 创建StaticProxy类,定义静态代理类
public class StaticProxy implements IProducer { private IProducer producer; public StaticProxy(IProducer producer){ this.producer=producer; } public void sale(float maney) { producer.sale(maney*0.8f); } }
- 测试(我这里使用的是单元测试,需要导入Juni依赖)
public class TestStaticProxy { IProducer producer=new Producer(); StaticProxy staticProxy=new StaticProxy(producer); @Test public void TestStaticProxy(){ //用户直接通过代理商购买商品,花了10000块, // 生产厂家得到了8000块,还有2000块是代理商的活动经费 //毕竟人家也要吃饭嘛 staticProxy.sale(10000f); } }
控制台打印信息:销售了商品,并拿到了钱:8000.0
JDK动态代理机制
代码实现
- 创建一个JDKDynamicProxy类,用来获取代理类对象
public class JDKDynamicProxy { IProducer producer=new Producer(); /** * 获取动态代理类对象 * @return */ public IProducer getProxy(){ IProducer proxyProducer = (IProducer) Proxy.newProxyInstance(producer.getClass().getClassLoader(), producer.getClass().getInterfaces(), new InvocationHandler() { public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { Float money = (Float) args[0]; method.invoke(producer,money*0.8f); return null; } }); return proxyProducer; } }
- 要求
被代理类至少实现一个接口 - 创建方式
Proxy.newProxyInstance(三个参数) - newProxyInstance方法三个参数
ClassLoader:和被代理对象使用相同的类加载器
Interface:和被代理对象具有相同的行为,实现相同的接口
InvocationHandler:如何代理 - InvocationHandler中的invoke方法详解
执行被代理对象的任何方法都会经过该方法
参数:
proxy:代理对象的引用
method:当前执行的被代理对象的方法的方法对象
args:执行被代理对象的方法所需的参数
返回值:当前执行的被代理对象的方法的返回值
- 测试
public class TestJDKDynamicProxy { JDKDynamicProxy jdkDynamicProxy=new JDKDynamicProxy(); @Test public void testJDKDynamicProxy(){ //获取代理对象 IProducer proxyProducer = jdkDynamicProxy.getProxy(); //执行此方法最终会执行InvocationHandler的的invoke方法 proxyProducer.sale(10000f); } }
控制台打印信息:销售了商品,并拿到了钱:8000.0
3. JDK动态代理的缺陷
- 被代理类必须实现接口
- 如果被代理类实现多个接口,在创建代理类对象时应该转向哪个类型
正是由于有这么多缺陷,于是有了CGLib动态代理
CGLib动态代理
- 要使用CGLib动态代理需要引入第三发依赖
<dependency> <groupId>cglib</groupId> <artifactId>cglib</artifactId> <version>3.2.5</version> </dependency>
- 创建CGLibProxy类,来获取代理对象
public class CGLibProxy { Producer producer=new Producer(); public Producer getProxy(){ Producer proxyProducer = (Producer) Enhancer.create(this.producer.getClass(), new MethodInterceptor() { public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable { Float money = (Float) objects[0]; method.invoke(CGLibProxy.this.producer, money*0.8f); return null; } }); return proxyProducer; } }
- 要求
被代理类不能是最终类 - 用到的类
Enhancer - 用到的方法
create(Class,Callback) - 方法参数
Class:被代理类字节码
Callback:如何代理
- 测试
public class TestCGLibProxy { CGLibProxy cgLibProxy=new CGLibProxy(); @Test public void testCGLibProxy(){ Producer proxyProducer = cgLibProxy.getProxy(); proxyProducer.sale(12000f); } }
控制台打印销售了商品,并拿到了钱:9600.0
相关文章推荐
- Java 动态代理机制分析及扩展,第 1 部分
- 彻底理解JAVA动态代理
- Java反射和动态代理详解和实例
- JAVA AOP面向切面编程与动态代理
- 动态代理---动态生成java文件并编译成class文件
- java动态代理
- 代理模式和java动态代理
- java 动态代理模式
- 《转》JAVA动态代理(JDK和CGLIB)
- [转]Java 动态代理机制分析及扩展
- 【Java】从源码分析动态代理机制
- 用JAVA动态代理实现AOP
- [java] JDK 的动态代理机制
- java 动态代理
- Java 动态代理
- java中的动态代理和CGLIB代理
- Java 读书笔记 14.7 动态代理
- java的动态代理机制详解
- Java动态代理二——CGLIB动态代理应用
- java的动态代理和反射