Java动态代理
最近在看java的动态代理,做下笔记
什么是代理
代购:如果你想买的东西在国外,你一般不会飞过去买完再飞回来,而是有个中介,帮你处理这件事,这个中介就是代购,也就是代理。帮你办一件事就是代理。
客户 —– 代理(代购) ——国外商场
为什么找代购?
便宜省心专业,我不能自己去国外买。同时代购为了自己的优势,不让买家接触自己的进货渠道,你想要这个价格和服务就只能通过代购。所以很多时候只能通过代购来买东西。
类比到java
A类想调用C类的方法,但是C不允许A直接调用,这时候可以通过代理B来进行操作。
A->B->C
C->B->A
看起来很傻对不对?但是是实际情况需求。
比如付款需要短信验证码,你不可能直接找移动联通说发条短信。而是找第三方公司,他们总包了一个大业务,一天几十万条给移动联通签合同。然后你买他们的,他们再付钱给移动联通。
代理模式
什么是代理模式
A类想调用C类的方法,但是C不允许A直接调用,这时候可以通过代理B来进行操作。这种程序的调用关系称为代理模式。
代理模式的作用
1、功能增强 :在原有功能上增加新功能
2、控制访问 : 控制你直接访问目标
如何实现代理
静态代理
1、代理类手动实现
2、代理的目标类是确定的
实现一个静态代理
1、创建一个接口,定义卖U盘的方法
2、创建厂家类,实现1步骤接口
3、创建商家,就是代理实现1步骤接口
4、定义客户类
定义UsbSell接口
1 |
|
金士顿厂家
1 | public class UsbKingFactory implements UsbSell{ |
淘宝商家
1 | public class TaoBao implements UsbSell{ |
客户
1 | public class ShopMain{ |
代理类一般都 会调用目标类的方法,然后额外做其他功能。
缺点
1、如果厂家不止一家,就要创建各种厂家类,然后代理商也要调用各种厂家类的方法。所以代理商类也成倍增长。
2、如果接口增减功能,所有实现此接口的所有类都会被影响。
动态代理
在程序执行过程中,使用jdk的反射机制,创建代理类对象,并动态指定代理的目标类。
作用
1、控制访问
2、功能增强
实现方式
1、JDK动态代理
反射包 java.lang.reflect 里面有三个类:InvocationHandler,Method,Proxy
其中 InvocationHandler接口有一个: invoke() 方法,我们需要实现这个接口并在invoke方法中完成下面的功能
1、调用目标方法
2、功能增强
为什么?因为这个 invoke() 会在动态代理对象调用任意方法的时候出发,是动态代理的核心。
怎么用?
1、创建类实现这个接口InvocationHandler?
2、重写invoke方法,把要完成的功能写在里面。
3、生成动态代理对象(生成动态代理对象的过程就是把动态的代码具体到某个类的动态代理对象)
4、执行对应方法。
例子
1、必须有接口,(比如一个Subject有一个doSomething方法)
2、必须有实现这个接口的类 (比如RealSubject实现这个接口,并且是一个类)
3、设计动态代理类ProxyHandler继承InvocationHandler,在invoke中 通过反射实时调用我们想调用的方法,并做功能增强,最终返回返回值。
4、应用动态代理:声明动态代理的类,生成动态代理对象(new RealSubject,并通过Proxy.newProxyInstance生成动态代理对象。)
特点:
1、无侵入式的代码扩展。
2、无需实现大量的类,可通过反射特性动态执行方法。
1 | package test; |
1 | package test; |
上面两块代码不是确定的,可以实现成千上万的接口和对应类,然后通过动态代理来动态调用和功能增强上面的类的对象。
下面就是动态代理类必须实现InvocationHandler接口,并在invoke中写下面的逻辑代码:1、调用目标对象方法 2、功能增强
(其中bind不是必须的,也可以在别的地方进行动态代理的生成,当然封装成bind函数在生成动态代理的时候更方便。)
1 | package test; |
1 | public class TestProxy |
看完代码,现在我来回答,动态代理的作用是什么:
- Proxy类的代码量被固定下来,不会因为业务的逐渐庞大而庞大;
- 可以实现AOP编程,实际上静态代理也可以实现,总的来说,AOP可以算作是代理模式的一个典型应用;
- 解耦,通过参数就可以判断真实类,不需要事先实例化,更加灵活多变。