java动态代理详解

代理都知道吧,你去买东西就有很多的代理商,他们就是卖原厂的东西。比如,你天天要买肉,猪是农民伯伯养的,但你是从屠夫手上买到肉的,这个屠夫就可以当成是代理。那为什么要代理呢,代理有什么用呢,当然是有事给他做了,对于屠夫这个代理就好理解了,因为你自己不可能去宰猪吧,所以代理就是去买活猪,然后宰掉再卖给你,当然屠夫有可能给肉注点水,关键看他坏不坏,所以屠夫的整个流程就是:

这个流程用代码怎么实现呢:我们应该要用三个类You、Butcher、Farmer分别指你、屠夫、农民伯伯。其中农民伯伯又提供一个买肉的方法给屠夫调用,这个方法输入是钱的数量,返回是肉的数量,都用int型,代码如下:

代码如下:

class Farmer {
    public int buyMeat(int money) {
        int meat = 0;
        // ... meat = ***;
        return meat;
    }
}

而屠夫则提供一个买肉的方法给你调用,同样是输入钱,返回肉,但是会把肉加工一下(杀猪和刮猪毛在代码中就省了,要不然还得为猪写个类),代码如下:

代码如下:

class Butcher {
    public int buyMeat(int money) {
        Farmer farmer = new Farmer();            // 1.find a farmer.
        int meat = farmer.buyMeat(money);        // 2.buy meat from the farmer.
        meat += 5;                               // 3.inject 5 pound water into the meat, so weight will increase.
        return meat;                             // 4.return to you.
    }
}

然你从屠夫手上买肉的代码就变成这样:

代码如下:

class You {
    public void work() {
        int youMoney = 10;
        Butcher butcher = new Butcher();        // find a butcher.
        int meat = butcher.buyMeat(youMoney);
        System.out.println("Cook the meat, weight: " + meat);  // you cooked it. 
    }
}

这个程序我们还可以优化一下,我们发现屠夫有农民有一个相同的买肉方法,我们可以提取一个接口,叫为商贩(pedlar)吧,以后你买肉就不用管他是屠夫还是农民伯伯了,只要他有肉卖就可以了,我们提取一个接口后,代码就变成这样:

代码如下:

class You {
    public void work() {
        int youMoney = 10;
        Peldar peldar= new Butcher();                               // find a peldar.
        int meat = peldar.buyMeat(youMoney);
        System.out.println("Cook the meat, weight: " + meat);        // you cooked it.   
    }
}
interface Peldar {
 int buyMeat(int money);
}
class Butcher implements Peldar {
    @Override
    public int buyMeat(int money) {
        Farmer farmer = new Farmer();            // 1.find a farmer.
        int meat = farmer.buyMeat(money);        // 2.buy meat from the farmer.
        meat += 5;                               // 3.inject 5 pound water into the meat, so weight will increase.
        return meat;                             // 4.return to you.
    }
}

class Farmer implements Peldar {
    @Override
    public int buyMeat(int money) {
        int meat = 0;
        // ... meat = ***;
        return meat;
    }
}

这就是代理,值得注意的是一般代理类和最终类会实现同一接口,这样的好处是,调用者就不用关心当前引用的到底是代理还是最终类。

不过这叫静态代理,因为代理类(屠夫类)是你亲手写,动态代理就是Java在运行的时候,动态生成一个等价的代理类。虽然类是动态生成的,但是杀猪和注水的代码还是要写的,只是不要写一个类了。写到哪里呢,写到下面这个接口里面:

代码如下:

public interface InvocationHandler {
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable;
}

参数是什么意思呢,我写成这样,可能你就明白了:

代码如下:

public interface InvocationHandler {
    public Object invoke(Object butcher, Method buyMeat, Object[] money) throws Throwable;
}

第一个参数是自动生成的代理类的一个对象(自动生成的屠夫类的对象),第二个参数是正前正在被调用的方法的对象(方法怎么还有对象呢,参见Java反射机制),我们这里只有一个方法叫buyMeat,所以这个参数代表的肯定就是它了,第三个参数是传给前面那个方法的参数数组,buyMeat只有一个参数,所以这个数组只会有一个元素。于是杀猪注水的代码写进来就变成这样了:

代码如下:

InvocationHandler mInvocationHandler = new InvocationHandler() {  
    @Override
    public Object invoke(Object butcher, Method buyMeat, Object[] args) throws Throwable {
        Farmer farmer = new Farmer();              // 1.find a farmer.
        int meat = (Integer) buyMeat.invoke(farmer, args);      // 2.buy meat from the farmer.
        meat += 5;                                 // 3.inject 5 pound water into the meat, so weight will increase.
        return meat;                               // 4.return to you.
    }
};

这个里调用农民伯伯的买肉方法有点不符常规,这里是反射机制调用法,意思是这样的,以farmer对象为接受者来调用buyMeat方法,跟直接调用farmer的方法是一样的,你可能会问那为什么不直接调用呢,你可能没注意,invoke的第一个参数类型是Object,所以你可以向任何对象发布调用命令(但不一定会成功,什么时候会成功等下说),如果你有很多farmer对象,甚至不是farmer对象,只要某接口的实例就可以(哪个接口等下说明,我们先命名为A接口),就可以当成参数传进来,然后对其进行方法调用。现在我们来看看如何生成代理类吧,很简单,可以调用Proxy的工厂方法,如下:

代码如下:

public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) 
    throws IllegalArgumentException

解释参数,第一个ClassLoader是用来加载代理类的(关于ClassLoader,本文暂不讲解),你暂不了解也没关系,第二个是一个数组,每个元数都是一个接口,新生成的代理都会实现所有这些接口,传给InvocationHandler.invoke第二个参数的方法,必定属于所有这些接口中的方法,上一段落说的那个A接口必须是数组中的一个元素,上一段落说的那个调用成失败问题也明了了。第三个参数InvocationHandler更好理解了,就是只要代理类中的任何方法被调用,就会通知这个InvocationHandler。下面写出完整代码:

代码如下:

class You {
    public void work() {
        int youMoney = 10;

Peldar peldarProxy = (Peldar) Proxy.newProxyInstance(getClass().getClassLoader(), new Class[]{Peldar.class}, mInvocationHandler);
        int meat = peldarProxy.buyMeat(youMoney);

System.out.println("Cook the meat, weight: " + meat);   
    }

InvocationHandler mInvocationHandler = new InvocationHandler() {       
        @Override
        public Object invoke(Object butcher, Method buyMeat, Object[] args)
                throws Throwable {
            Farmer farmer = new Farmer();                           // 1.find a farmer.
            int meat = (Integer) buyMeat.invoke(farmer, args);      // 2.buy meat from the farmer.
            meat += 5;                                              // 3.inject 5 pound water into the meat, so weight will increase.
            return meat;                                            // 4.return to you.
        }
    };

}
interface Peldar {
    int buyMeat(int money);
}

class Farmer implements Peldar {
    @Override
    public int buyMeat(int money) {
        int meat = 0;
        // ... meat = ***;
        return meat;
    }
}

这里You类里生成一个代理类,在代理类的buyMeat被调用时,代码就跟之前的静态代理一样的了。

(0)

相关推荐

  • java代理模式与动态代理模式详解

    1.代理模式 所谓代理,就是一个人或者一个机构代表另一个人或者另一个机构采取行动.在一些情况下,一个客户不想或者不能够直接引用一个对象,而代理对象可以在客户端和目标对象之前起到中介的作用.代理模式给某一个对象提供一个代理对象,并由代理对象控制对原对象的引用. 生活中的例子:过年加班比较忙,没空去买火车票,这时可以打个电话到附近的票务中心,叫他们帮你买张回家的火车票,当然这会附加额外的劳务费.但要清楚票务中心自己并不卖票,只有火车站才真正卖票,票务中心卖给你的票其实是通过火车站实现的.这点很重要!

  • 十分钟理解Java中的动态代理

    若代理类在程序运行前就已经存在,那么这种代理方式被成为 静态代理 ,这种情况下的代理类通常都是我们在Java代码中定义的. 通常情况下, 静态代理中的代理类和委托类会实现同一接口或是派生自相同的父类. 一.概述 1. 什么是代理 我们大家都知道微商代理,简单地说就是代替厂家卖商品,厂家"委托"代理为其销售商品.关于微商代理,首先我们从他们那里买东西时通常不知道背后的厂家究竟是谁,也就是说,"委托者"对我们来说是不可见的;其次,微商代理主要以朋友圈的人为目标客户,这就

  • 基于接口实现java动态代理示例

    Subject.java 复制代码 代码如下: package _20140416_; import java.util.List; public interface Subject {   public String say(String name,int age);   public List<Person> getAllList(String name);} RealSubject.java 复制代码 代码如下: package _20140416_; import java.util.

  • Java动态代理的应用详解

    动态代理其实就是java.lang.reflect.Proxy类动态的根据您指定的所有接口生成一个class byte,该class会继承Proxy类,并实现所有你指定的接口(您在参数中传入的接口数组):然后再利用您指定的classloader将 class byte加载进系统,最后生成这样一个类的对象,并初始化该对象的一些值,如invocationHandler,以即所有的接口对应的Method成员. 初始化之后将对象返回给调用的客户端.这样客户端拿到的就是一个实现你所有的接口的Proxy对象

  • 详解Java动态代理的实现机制

    一.概述 代理是一种设计模式,其目的是为其他对象提供一个代理以控制对某个对象的访问,代理类负责为委托类预处理消息,过滤消息并转发消息以及进行消息被委托类执行后的后续处理.为了保持行为的一致性,代理类和委托类通常会实现相同的接口. 按照代理的创建时期,代理类可分为两种: 静态代理:由程序员创建代理类或特定工具自动生成源代码再对其编译,也就是说在程序运行前代理类的.class文件就已经存在. 动态代理:在程序运行时运用反射机制动态创建生成. 下面在将动态代理的实现机制之前先简单介绍一下静态代理. 二

  • Java动态代理实现_动力节点Java学院整理

    动态代理作为代理模式的一种扩展形式,广泛应用于框架(尤其是基于AOP的框架)的设计与开发,本文将通过实例来讲解Java动态代理的实现过程. 通常情况下,代理模式中的每一个代理类在编译之后都会生成一个class文件,代理类所实现的接口和所代理的方法都被固定,这种代理被称之为静态代理(Static Proxy).那么有没有一种机制能够让系统在运行时动态创建代理类?答案就是本文将要介绍的动态代理(Dynamic Proxy).动态代理是一种较为高级的代理模式,它在事务管理.AOP(Aspect-Ori

  • 代理模式之Java动态代理实现方法

    今天一个偶然的机会我突然想看看JDK的动态代理,因为以前也知道一点,而且只是简单的想测试一下使用,使用很快里就写好了这么几个接口和类:接口类:UserService.java 复制代码 代码如下: package com.yixi.proxy;public interface UserService {    public int save() ;    public void update(int id);} 实现类:UserServiceImpl.java 复制代码 代码如下: packag

  • 详解java中动态代理实现机制

    代理模式是常用的java设计模式,它的特征是代理类与委托类有同样的接口,代理类主要负责为委托类预处理消息.过滤消息.把消息转发给委托类,以及事后处理消息等.代理类与委托类之间通常会存在关联关系,一个代理类的对象与一个委托类的对象关联,代理类的对象本身并不真正实现服务,而是通过调用委托类的对象的相关方法,来提供特定的服务. JAVA各种动态代理实现的比较 接口 interface AddInterface{ int add(int a, int b); } interface SubInterfa

  • java实现动态代理方法浅析

    一些Java项目中在mybatis与spring整合中有MapperScannerConfigurer的使用,该类通过反向代理自动生成基于接口的动态代理类. 有鉴于此,本文浅析了java的动态代理. 本文使用动态代理模拟处理事务的拦截器. 接口: public interface UserService { public void addUser(); public void removeUser(); public void searchUser(); } 实现类: public class

  • Java动态代理详解及实例

    Java动态代理 代理设计模式 定义:为其他对象提供一种代理以控制对这个对象的访问. 动态代理使用 java动态代理机制以巧妙的方式实现了代理模式的设计理念. 代理模式示例代码 public interface Subject { public void doSomething(); } public class RealSubject implements Subject { public void doSomething() { System.out.println( "call doSom

  • java动态代理详解

    代理都知道吧,你去买东西就有很多的代理商,他们就是卖原厂的东西.比如,你天天要买肉,猪是农民伯伯养的,但你是从屠夫手上买到肉的,这个屠夫就可以当成是代理.那为什么要代理呢,代理有什么用呢,当然是有事给他做了,对于屠夫这个代理就好理解了,因为你自己不可能去宰猪吧,所以代理就是去买活猪,然后宰掉再卖给你,当然屠夫有可能给肉注点水,关键看他坏不坏,所以屠夫的整个流程就是: 这个流程用代码怎么实现呢:我们应该要用三个类You.Butcher.Farmer分别指你.屠夫.农民伯伯.其中农民伯伯又提供一个买

  • 超全MyBatis动态代理详解(绝对干货)

    前言 假如有人问你这么几个问题,看能不能答上来 Mybatis Mapper 接口没有实现类,怎么实现的动态代理 JDK 动态代理为什么不能对类进行代理(充话费送的问题) 抽象类可不可以进行 JDK 动态代理(附加问题) 答不上来的铁汁,证明 Proxy.Mybatis 源码还没看到位.不过没有关系,继续往下看就明白了 动态代理实战 众所周知哈,Mybatis 底层封装使用的 JDK 动态代理.说 Mybatis 动态代理之前,先来看一下平常我们写的动态代理 Demo,抛砖引玉 一般来说定义 J

  • java 中动态代理详解及实例

    Java动态代理相关 先来看静态代理模式代码: package test; public interface Subject { public void doSomething(); } package test; public class RealSubject implements Subject{ public void doSomething() { System.out.println( "call doSomething()" ); } } package test; pu

  • java 反射和动态代理详解及实例代码

    一.java中的反射 1.通过反射加载类的属性和方法实例代码: /** * java.lang.Class 是反射的源头 * 我们创建了一个类,通过编译(javac.exe)生成对应的class文件,之后我们通过java.exe加载(jvm的类加载器加载)此class文件 * 此class文件加载到内存后,就是一个运行时类,存在缓存区,这个运行时类本事就是一个Class的实例 * 每一个运行时类只加载一次, */ Class<StudentExam> clazz = StudentExam.c

  • java jdk动态代理详解

    jdk动态代理要对一个类进行代理,被代理的类必须实现至少一个接口,并且只有接口中的方法才能被代理. jdk实现动态代理一般分为三步: 1. 编写接口和实现类. 2. 写一个处理器,该处理器实现InvocationHandler接口,该接口只有一个方法,其签名为public Object invoke(Object proxy, Method method, Object[] args)throws Throwable;可在该处理器的实现方法中,在方法调用前和调用后加入自己的代码,从而进行动态拦截

  • jdk动态代理和cglib动态代理详解

    目录 静态代理 基于继承的方式实现静态代理 基于聚合的方式实现静态代理 继承与聚合方式实现的静态代理对比 动态代理 JDK动态代理 如何实现一个HashMap的动态代理类? Cglib动态代理 JDK与Cglib动态代理对比? 动态代理和静态代理的区别? Spring如何选择两种代理模式的? 总结 如上图,代理模式可分为动态代理和静态代理,我们比较常用的有动态代理中的jdk动态代理和Cglib代理,像spring框架.hibernate框架中都采用了JDK动态代理,下面将结合代码阐述两种代理模式

  • 详解JAVA动态代理

    文档更新说明 2018年09月24日 v1.0 初稿 代理在生活中很常见,比如说婚介网站,其实就是找对象的代理:还有社保代理.人事代理:还有找黄牛抢票,其实也是一种代理:而这些代理,在JAVA中也是有对应实现的. 1.为什么要动态代理 动态代理的作用其实就是在不修改原代码的前提下,对已有的方法进行增强. 关键点: 不修改原来已有的代码(满足设计模式的要求) 对已有方法进行增强 2.举个栗子 我们用一个很简单的例子来说明:Hello类,有一个introduction方法. 现在我们的需求就是不修改

  • 详解Java动态代理的实现及应用

    详解Java动态代理的实现及应用 Java动态代理其实写日常业务代码是不常用的,但在框架层一起RPC框架的客户端是非常常见及重要的.spring的核心思想aop的底层原理实现就使用到了java的动态代理技术. 使用代理可以实现对象的远程调用以及aop的实现. java的动态代理的实现,主要依赖InvoctionHandler(接口)和Proxy(类)这两个. 下面是一个例子 实现的代理的一般需要有个接口 package com.yasin.ProxyLearn; public interface

  • Java动态代理(设计模式)代码详解

    基础:需要具备面向对象设计思想,多态的思想,反射的思想: Java动态代理机制的出现,使得Java开发人员不用手工编写代理类,只要简单地指定一组接口及委托类对象,便能动态地获得代理类.代理类会负责将所有的方法调用分派到委托对象上反射执行,在分派执行的过程中,开发人员还可以按需调整委托类对象及其功能,这是一套非常灵活有弹性的代理框架.通过阅读本文,读者将会对Java动态代理机制有更加深入的理解.本文首先从Java动态代理的运行机制和特点出发,对其代码进行了分析,推演了动态生成类的内部实现. 代理模

随机推荐