代理模式
代理模式的分类:
- 静态代理
- 动态代理
-------------------------------------------------------------------------------------------------------------------
静态代理
代码步骤:
- 接口(提取关键方法)
- 真实角色(原本的实现对象)
- 代理角色(扩展功能)
- 客户端访问代理角色(方法增强的结果)
1 //租房 2 public interface Rent { 3 void rent(); 4 }
1 //真实角色 房东 2 public class Host implements Rent { 3 public void rent() { 4 System.out.println("房东出租房子"); 5 } 6 }
1 //代理角色房屋中介 2 public class proxy implements Rent { 3 private Host host; 4 5 public proxy(){ 6 7 } 8 public proxy(Host host){ 9 this.host= host; 10 } 11 12 public void rent() { 13 host.rent(); 14 seeHouses(); 15 hetong(); 16 fare(); 17 } 18 public void seeHouses(){ 19 System.out.println("中介带你看房子"); 20 } 21 public void fare (){ 22 System.out.println("中介收中介费"); 23 24 } 25 public void hetong(){ 26 System.out.println("中介签署租房合同"); 27 } 28 }
//调用真实角色的方法的人 public class Client { public static void main(String[] args) { Host host = new Host(); proxy p = new proxy(host); //此时代理角色可以执行一些附属操作,这就是代理的意义所在 p.rent(); } }
/*输出 房东出租房子
中介带你看房子
中介签署租房合同
中介收中介费*/
静态代理模式的好处:
可以使真实角色的操作更加纯粹!不用去关注一些公共的事务;
公共的业务就交给代理角色!实现了业务的分工;
公共业务发生扩展的时候,方便集中管理!
缺点:
一个真实角色就会产生一个代理角色;代码量会翻倍,开发的效率会变低
==========================================================================================================================================================
动态代理(底层原理是反射)
解决静态代理的缺点
- 动态代理和静态代理的角色是一样的;
- 动态代理的代理类是自动生成的,不是提前写好的
- 动态代理分为两大类:基于接口的动态代理,基于类的动态代理
---基于接口:JDK的动态代理[使用本方法实现]
---基于类:cglib
---java字节码实现:JAVAsist
重点的两个类
Proxy
Proxy提供了创建动态代理类和实例的静态方法,它也是由这些方法创建的所有动态代理类的超类。
为某个接口创建代理Foo :
InvocationHandler handler = new MyInvocationHandler(...);
Foo f = (Foo) Proxy.newProxyInstance(Foo.class.getClassLoader(), new Class<?>[] { Foo.class }, handler);
Interface InvocationHandler (调用处理程序)位于reflet反射包下
参数
proxy - 调用该方法的代理实例
method -所述方法对应于调用代理实例上的接口方法的实例。 方法对象的声明类将是该方法声明的接口,它可以是代理类继承该方法的代理接口的超级接口。
args -包含的方法调用传递代理实例的参数值的对象的阵列,或null如果接口方法没有参数。 原始类型的参数包含在适当的原始包装器类的实例中
接口
1 package com.wzy.proxy.dynamicproxy; 2 //租房 3 public interface Rent { 4 void rent(); 5 }
1 package com.wzy.proxy.dynamicproxy; 2 3 //真是角色 房东 4 public class Host implements Rent { 5 public void rent() { 6 System.out.println("房东出租房子"); 7 } 8 }
1 //会用这个类自动生成代理类 2 public class ProxyInvocationHandler implements InvocationHandler { 3 //被代理接口 4 private Rent rent; 5 6 public void setRent(Rent rent) { 7 this.rent = rent; 8 } 9 10 //生成代理类 11 public Object getProxy(){ 12 return Proxy.newProxyInstance(this.getClass().getClassLoader(), rent.getClass().getInterfaces(), this); 13 } 14 15 //处理代理实例.并返回结果 16 //调用代理程序的执行方法 17 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { 18 //动态代理本质,使用了反射的机制 19 seeHouse(); 20 Object result = method.invoke(rent, args); 21 fare(); 22 return result; 23 } 24 public void seeHouse(){ 25 System.out.println("中介带看房子"); 26 } 27 public void fare(){ 28 System.out.println("中介收中介费"); 29 } 30 31 }
1 public class Client { 2 3 public static void main(String[] args) { 4 //真实角色 5 Host host = new Host(); 6 7 //代理角色:现在没有 8 ProxyInvocationHandler pih = new ProxyInvocationHandler(); 9 10 // 通过调用程序处理角色来处理我们要调用的接口实现对象 ! 11 pih.setRent(host);//设置要代理对象 12 13 Rent proxy = (Rent) pih.getProxy();//这里的proxy就是动态生成的代理对象 14 15 proxy.rent(); 16 17 } 18 }
输出:
中介带看房子
房东出租房子
中介收中介费
动态代理的好处:
可以使真实角色的操作更加纯粹!不用去关注一些公共的事务;
公共的业务就交给代理角色!实现了业务的分工;
公共业务发生扩展的时候,方便集中管理!
一个动态代理类代理的是一个接口,一般就是对应的一类业务
一个动态代理类可以代理多个类,只要是实现了同一个接口即可
The flash that cuts through darkness, the light that breaks the night.