代理模式
代理模式定义:代理模式给某一个对象提供一个代理对象,并由代理对象控制对原对象的引用
举三个例子:
1:支付宝付款,我们平时付款只要知道付多少钱就行,至于从哪张银行卡上扣钱,由Ali负责
2:结婚时,你只需要和新娘结婚就行,至于布置婚礼场所可以由婚办公司去布置
3:中介,房东出租房子,需要把自己要出租的房子交给中介,让他去出租
-
spring Aop的底层实现是代理模式(动态代理)
在这里可以考虑下多线程里thread(new thread1()).start()是代理?以及IO中的BufferedReader(FileBufferedReader())是代理?如果不是它们又是什么?
4:代理模式分类:
-
静态代理
- 动态代理
静态代理:
-
静态代理有4个角色:
-
抽象角色: 一般会使用接口或者抽象类去解决
-
真实角色:被代理的对象
-
代理角色:代理真实角色,代理真实角色后,一般会做一些附属操作
-
客户:访问代理对象的人
下面代码以中介为例子(没有写客户,因为客户和房东性质差不多,客户找房子也要去找代理):
抽象角色:出租房接口
public interface Rent { public void rent(); }真实角色:房东类(实现出租房这个接口)
public class Host implements Rent{ @Override public void rent() { // TODO Auto-generated method stub System.out.println("房东要出租房子"); }代理角色:
public class Proxy implements Rent{ private Host host; public Proxy(Host host) { this.host = host; } @Override public void rent() { // TODO Auto-generated method stub host.rent(); fare(); house(); } //以下是中介附属的方法,人家不可能无缘无故帮你做的 public void fare(){ System.out.println("收代理费"); } public void house(){ System.out.println("去看房东要出租的房子"); } } main类
public class Main { /** * @Title: main * @Description: TODO * @param @param args * @return void * @throws */ public static void main(String[] args) { // TODO Auto-generated method stub //房东要出租房子,但找不到租房子的人,只能交给代理去做 Host host=new Host(); //帮房东赵租房子的人,但会带一些附属操作,人家不可能无缘无故帮你的 Proxy px=new Proxy(host); px.rent(); }main方法里也可以用匿名对象写,就像我上面写的多线程那个对象
动态代理:
动态代理依靠反射包下(InvocationHandler,proxy)来动态生成一个动态代理类生成的,不是像静态代理那样去直接写好的
invocationHandler(是一个接口):是由代理实例调用处理程序实现的接口(类似于上面静态里的出租房子那个接口,只是这个接口中有invoke方法,里面利用反射机制,将里面的成分反射成相应的类)
proxy:提供了创建动态代理类和实例的静态方法
每个代理实例都有一个关联的调用程序接口,当在代理实例上调用方法时,方法调用将被编码分配到其调用处理程序的invoke()方法
动态代理分为两大类:基于接口动态代理和基于类的动态代理
基于接口:依赖于jdk
基于类:cglib
角色和静态代理角色一样
代码演示:
抽象角色:出租房子接口
public interface Rent { public void rent(); }产生代理类的类(动态代理类的对象是抽象透明的,因为本身代理类都是靠里面反射机制产生的):
public class ProxyInvocationHandler implements InvocationHandler{ //被代理的接口 private Rent rent; public void setRent(Rent rent){ this.rent=rent; } //生成得到代理类 public Object getProxy(){ return Proxy.newProxyInstance(this.getClass().getClassLoader(), rent.getClass().getInterfaces(), this); } //处理代理实例并返回结果 @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { // TODO Auto-generated method stub //利用反射机制实现 Object result=method.invoke(rent, args); return result; }main类
public class Main { public static void main(String[] args) { // TODO Auto-generated method stub //真实角色 Host host=new Host(); //通过调用程序处理角色来处理我们要调用的接口对象 ProxyInvocationHandler pih=new ProxyInvocationHandler(); pih.setRent(host); /* Proxy.newProxyInstance(this.getClass().getClassLoader(), rent.getClass().getInterfaces(), this);*/ //getProxy()方法这里有我们的代理的接口,和可以产生代理类的类 Rent proxy=(Rent)pih.getProxy(); proxy.rent(); } }静态代理优点:
便于简单业务操作,扩展原功能,不侵入源代码
缺点:
容易出现代码冗余,开发效率降低,不利于维护
静态代理与动态代理比较
动态代理比较好,它不仅基本上拥有静态代理的优点,
一个动态代理类可以代理多个真实类pih.setRent(host),只要把里面对象换了便可,但要实现同一个接口<!--希望看了此文章的人,如果里面哪里有错了提出来-->