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 }
  • 相关阅读:
    linux下拼接字符串的代码
    postgresql实现插入数据返回当前的主键ID
    记录一个linux下批处理的代码
    iptables
    mybatis获得执行insert的返回值
    git commit之后撤销
    仿照CIFAR-10数据集格式,制作自己的数据集
    C/C++ 在处理文件所在路径下创建子目录
    C/C++ 图像二进制存储与读取
    C/C++ 文件路径解析
  • 原文地址:https://www.cnblogs.com/hacket/p/3051828.html
Copyright © 2011-2022 走看看