zoukankan      html  css  js  c++  java
  • 代理静态代理和动态代理

    静态代理

      

    1、接口类

    1 public interface Star {
    2     public void sing();
    3 }

    2、被代理类

    1 public class Liyuchun implements Star {
    2     public void sing() {
    3         System.out.println("春哥唱歌");
    4     }
    5 }

    3、代理类

     1 public class LiyuchunProxy implements Star {
     2     private Liyuchun liyuchun = new Liyuchun();
     3     public void sing() {
     4         liyuchun.sing();
     5     }
     6     //基于接口编程
     7     public Star getProxy() {
     8         return liyuchun;
     9     }
    10 }

    4、用户

     1 //哥/歌迷
     2 public class Fans {
     3     public static void main(String[] args) {
     4         //创建代理对象
     5         LiyuchunProxy liyuchunProxy = new LiyuchunProxy();
     6         //通过代理对象找目标对象
     7         Star star = liyuchunProxy.getProxy();
     8         //业务方法
     9         star.sing();
    10     }
    11 }

     动态代理

      动态代理(代理类产生代理对象)

    明确两个概念:
    •代理对象存在的价值:主要用于拦截对真实业务对象的访问。
    •代理对象有什么方法?与真实对象相同,只是无业务代码。

      现在要生成某一个对象的代理对象,这个代理对象通常也要编写一个类来生成,所以首先要编写用于生成代理对象的类,即代理类的对象。

      如何编写生成代理对象的类,两个要素:

    •代理谁
    •如何生成代理对象
    代理谁?
      •设计一个类变量,以及一个构造函数,记住代理类代理哪个对象。

    如何生成代理对象?(invoke方法)

      •设计一个方法生成代理对象(在方法内编写代码生成代理对象是此处编程的难点)

          

    Java提供了一个Proxy类,调用它的newInstance()方法可以生成某个对象的代理对象,使用该方法生成代理对象时,需要三个参数:
    •1.生成代理对象使用哪个类加载器ClassLoader
    •2.生成哪个对象的代理对象,通过接口指定
    •3.生成的代理对象的方法里干什么事,由开发人员编写handler接口的实现来指定。
     
    初学者必须记住的2件事情:
    •Proxy类负责创建代理对象时,如果指定了handler(处理器),那么不管用户调用代理对象的什么方法,该方法都是调用处理器的invoke方法。
    •由于invoke方法被调用需要三个参数:代理对象、方法、方法的参数,因此不管代理对象哪个方法调用处理器的invoke方法,都必须把自己所在的对象、自己(调用invoke方法的方法)、方法的参数传递进来。
     
    开发步骤:

    1)写一个普通类,无需任何继承或实现
    2)写一个实例变量,记住代理谁,即目标对象
    3)使用构造方法为实例变量赋值
    4)写一个普通方法,该方法的返回值是接口,该接口是目标对象的实现接口

    1、接口类

    1 public interface Star {
    2     
    3     public void sing();
    4     public void sing(String money);
    5 }

    2、被代理类

    1 //    目标对象
    2 public class Liyuchun implements Star {
    3     public void sing() {
    4         System.out.println("春哥唱歌");
    5     }
    6     public void sing(String money){
    7         System.out.println("春哥的"+money+"万出场费,春哥开始唱歌了");
    8     }
    9 }

    3、代理类

     1 import java.lang.reflect.InvocationHandler;
     2 import java.lang.reflect.Method;
     3 import java.lang.reflect.Proxy;
     4 
     5 //    代理类
     6 public class LiyuchunProxy {
     7 
     8 //    代理谁,通过构造方法赋值
     9     private static Liyuchun liyuchun = new Liyuchun();
    10     
    11 //    基于接口编程,动态产生代理对象
    12     /*
    13      *     参数一:loader表示动态代理对象是由哪个类加载器完成的
    14         参数二:interfaces表示动态代理对象与目标对象(春哥)有一样的方法,即相当于获取目标对象(即被代理类)的方法
    15         参数三:表示动态代理对象的栏截方法,即每次调用目标对象都会执行该invoke()方法(难点)
    16 
    17     */
    18     public Star getProxy() {
    19         
    20         ClassLoader classLoader = LiyuchunProxy.class.getClassLoader();
    21         @SuppressWarnings("unchecked")
    22         Class<Liyuchun>[] interfaces = (Class<Liyuchun>[]) liyuchun.getClass().getInterfaces();
    23         
    24         return  (Star) Proxy.newProxyInstance(
    25                 classLoader, //参数一
    26                 interfaces , //参数二
    27                 new InvocationHandler() { //参数三
    28                     
    29                     public Object invoke(
    30                             Object proxy, 
    31                             Method method, //代理类的方法
    32                             Object[] args//代理类的参数,第一个参数为args[0],第二个为args[1],以此类推
    33                             )throws Throwable 
    34                     {
    35                         /*System.out.println("方法名:"+method.getName());*/
    36                         //System.out.println(method);
    37                         if("sing".equals(method.getName())){
    38 //                            调用春哥sing方法
    39                             String money = (String) args[0];
    40                             if(Integer.parseInt(money)>=3){
    41                                 method.invoke(liyuchun, money);
    42                             }else{
    43                                 System.out.println("春哥的出场费不够");
    44                             }
    45                         }
    46                         return null;
    47                     }
    48                 });
    49     }
    50 }

      4、用户

     1 //    歌迷类
     2 public class Fans  {
     3 
     4     public static void main(String[] args) {
     5 //        创建代理对象
     6         LiyuchunProxy liyuchunProxy = new LiyuchunProxy();
     7 //        通过代理对象找目标对象
     8         Star star = liyuchunProxy.getProxy();
     9 //        业务方法
    10         //star.sing();
    11         star.sing("3");
    12     }
    13 }
  • 相关阅读:
    CodeForces gym Nasta Rabbara lct
    bzoj 4025 二分图 lct
    CodeForces 785E Anton and Permutation
    bzoj 3669 魔法森林
    模板汇总——快读 fread
    bzoj2049 Cave 洞穴勘测 lct
    bzoj 2002 弹飞绵羊 lct裸题
    HDU 6394 Tree 分块 || lct
    HDU 6364 Ringland
    nyoj221_Tree_subsequent_traversal
  • 原文地址:https://www.cnblogs.com/hacket/p/3051828.html
Copyright © 2011-2022 走看看