后台(29)——动态代理

探索Android软键盘的疑难杂症
深入探讨Android异步精髓Handler
详解Android主流框架不可或缺的基石
站在源码的肩膀上全解Scroller工作机制



Android多分辨率适配框架(1)— 核心基础
Android多分辨率适配框架(2)— 原理剖析
Android多分辨率适配框架(3)— 使用指南



自定义View系列教程00–推翻自己和过往,重学自定义View
自定义View系列教程01–常用工具介绍
自定义View系列教程02–onMeasure源码详尽分析
自定义View系列教程03–onLayout源码详尽分析
自定义View系列教程04–Draw源码分析及其实践
自定义View系列教程05–示例分析
自定义View系列教程06–详解View的Touch事件处理
自定义View系列教程07–详解ViewGroup分发Touch事件
自定义View系列教程08–滑动冲突的产生及其处理



本文已经deprecated,关于动态代理,请参见从狡猾的房产中介来看动态代理


版权声明


代理模式简介

代理模式(Proxy Pattern)是面向对象中一种非常常见的设计模式。其实,不单是在软件开发领域,在我们的日常生活中对于代理也时常可见。比如:房东要将自家的房租出售,于是到房地产中介公司找一个代理,由他来帮自己完成销售房屋,签订合同等等事宜。

在此,就以该生活场景为蓝本介绍Java的代理模式。


静态代理

房东通过一纸协议将自己的房子挂靠在房屋中介;嗯哼,我们来一起瞅瞅这个房东和中介公司共同达成的协议:

/**
 * 本文作者:谷哥的小弟
 * 博客地址:http://blog.csdn.net/lfdfhl
 */
package cn.com;

public interface TradeProtocol {
    public void sellHouse(int money);
}

嗯哼,这个协议很简单,房东委托中介公司售卖自己的房子。

既然是房东和房屋中介共同达成的协议,那么房东和中介都需要遵守该协议。

先来看房东:

/**
 * 本文作者:谷哥的小弟
 * 博客地址:http://blog.csdn.net/lfdfhl
 */
package cn.com;

public class Owner implements TradeProtocol{

    @Override
    public void sellHouse(int money) {
        System.out.println("我是房主,我的房子卖了"+money+"块钱");
    }

}

再来看中介:

/**
 * 本文作者:谷哥的小弟
 * 博客地址:http://blog.csdn.net/lfdfhl
 */
package cn.com;

public class HouseAgent implements TradeProtocol {
    private TradeProtocol mHouseProtocol;

    public HouseAgent(TradeProtocol houseProtocol){
        mHouseProtocol=houseProtocol;
    }
    @Override
    public void sellHouse(int money) {
        System.out.println("我是中介,业主的房子卖了"+money+"块钱");
        mHouseProtocol.sellHouse(money);
    }

}

请注意HouseAgent的实现

  • 在HouseAgent的构造方法中传入TradeProtocol的对象比如Owner
  • 在HouseAgent的sellHouse()中调用TradeProtocol的对象(比如Owner)的sellHouse()
  • 所以,HouseAgent售卖(sellHouse())房子,实际上是房东售卖了房屋

测试如下:

/**
 * 本文作者:谷哥的小弟
 * 博客地址:http://blog.csdn.net/lfdfhl
 */
package cn.com;

public class Test {

    public static void main(String[] args) {
        Owner owner=new Owner();
        HouseAgent houseAgent=new HouseAgent(owner);
        houseAgent.sellHouse(10000*100);
    }

}

测试结果:

我是中介,业主的房子卖了1000000块钱
我是房主, 我的房子卖了 1000000块钱

在该静态代理中,房东将房屋的售卖交给了中介代理,中介将房屋出售后又把钱一分不少地交给了房东。咦,这咋不对呢?现实中有这样大公无私,视金钱如粪土的房屋中介么?没有!绝对没有!

那么,中介是怎么赚钱的呢?我们继续往下看


动态代理

与之前一样,房东和中介之间存有一纸协议:

/**
 * 本文作者:谷哥的小弟
 * 博客地址:http://blog.csdn.net/lfdfhl
 */
package cn.com;

public interface TradeProtocol {
    public void sellHouse(int money);
}

房东遵守该协议:

/**
 * 本文作者:谷哥的小弟
 * 博客地址:http://blog.csdn.net/lfdfhl
 */
package cn.com;

public class Owner implements TradeProtocol{

    @Override
    public void sellHouse(int money) {
        System.out.println("我是房主,中介告诉我:房子卖了"+money+"块钱");
    }

}

现在,房东又去房屋中介公司挂靠自己的房子,到了那一看:原来熟悉的那个代理出去办事了,刚好不在。正准备走呢,中介公司的经理挺着啤酒肚走过来,笑嘻嘻地说:请问您是来办理业务的吗?来,请坐,我给你们引荐以为我们这里服务最好的一个房屋代理人员办理您的相关事宜

嗯哼,我们来看看这个代理是怎么卖掉房东的房子的:

/**
 * 本文作者:谷哥的小弟
 * 博客地址:http://blog.csdn.net/lfdfhl
 */
package cn.com;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class Test {

    public static void main(String[] args) {
        TradeProtocol owner=new Owner();
        ClassLoader classLoader=owner.getClass().getClassLoader();
        Class<?>[] interfaces = owner.getClass().getInterfaces();
        TradeProtocol houseAgent=(TradeProtocol) Proxy.newProxyInstance(classLoader,interfaces, new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args)throws Throwable {
                Object object=null;
                System.out.println("我是中介,业主的房子我实际卖了"+args[0]+"块钱");
                object=method.invoke(owner, new Object[]{(Integer)args[0]/2});
                System.out.println("我是中介,这次交易我赚了不少钱呢");
                return object;
            }
        });
        houseAgent.sellHouse(10000*100);
    }

}

在该实现中由系统自动地为我们创建了一个代理Proxy.newProxyInstance()

结果如下:

我是中介,业主的房子我实际卖了1000000块钱
我是房主,中介告诉我:房子卖了500000块钱
我是中介,这次交易我赚了不少钱呢

哇哈,中介把房子卖了100W却告诉房东只买了50W,自己狠狠地赚了一笔!

嗯哼,这个例子我们看完了,在此对照Test类分析动态代理的实现

  • 动态代理与静态模式的原理是一样的,只是它没有具体的代理类而是通过Proxy在JVM运行时利用反射动态地生成了一个代理。
  • 请注意Proxy.newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h)方法的三个参数
    • ClassLoader:类加载器,传入和被代理类使用的相同的类加载器即可
    • Class<?>[] interface:代理类要实现的接口,传入和被代理类使用的相同的接口即可
    • InvocationHandler h:当通过代理对象调用一个方法的时候,该方法的调用会被转发至InvocationHandler接口的invoke()方法来执行具体的调用
  • 请注意invoke(Object proxy, Method method, Object[] args)方法的三个参数
    • Object proxy:代理对象的引用
    • Method method:当前调用的方法
    • Object[] args:当前调用的方法的输入参数
  • 由此可见:动态代理可方便地对委托类的方法进行某些处理,比如在方法实际调用前做一些过滤或者拦截操作,在方法调用后做一些善后处理等

后会有期

我们会在学习Spring框架时对Java动态代理机制做进一步的认识和理解

时间: 2024-08-31 11:21:22

后台(29)——动态代理的相关文章

JAVA核心层--反射--动态代理

本文发表于2010年,时间较早,部分问题解释不是十分准确,所以需要进一步了解,请参看2012年版本: java之架构基础-动态代理&cglib 要在JAVA技术上突破普通的层面,并拥有一翻设计理念的高度,除了要有很好的设计思维之外,反射在适当的使用下,将会把框架做得非常清晰,并且代码编写也非常简便. 在面向对象的编程中,我们为什么要忌讳去大量使用if else switch语句,因为这样写是将逻辑硬编码了,JAVA的思想就是将其配置化,一旦可配置化后,就逐渐可管理化,并随着产品的成熟逐步实现自动

Android插件化原理解析——Hook机制之动态代理

转发必注明出处:Hook机制之动态代理 使用代理机制进行API Hook进而达到方法增强是框架的常用手段,比如J2EE框架Spring通过动态代理优雅地实现了AOP编程,极大地提升了Web开发效率:同样,插件框架也广泛使用了代理机制来增强系统API从而达到插件化的目的.本文将带你了解基于动态代理的Hook机制. 阅读本文之前,可以先clone一份 understand-plugin-framework,参考此项目的dynamic-proxy-hook模块.另外,插件框架原理解析系列文章见索引.

跟屌丝大哥学习设计模式---代理模式之动态代理

动态代理 java中动态代理机制的引入使得代理模式的思想更加完善与进步,它允许动态的创建代理并支持对动态的对所代理的方法进行调用.Java动态代理类位于Java.lang.reflect包下,一般主要涉及到以下两个类:  (1). Interface InvocationHandler:该接口中仅定义了一个方法Object:invoke(Object obj,Method method, Object[] args).在实际使用时,第一个参数obj一般是指代理类,method是被代理的方法,如上

Java 动态代理(Proxy)

动态代理可以提供对另一个对象的访问,同时隐藏实际对象的具体事实,代理对象对客户隐藏了实际对象.动态代理可以对请求进行其他的一些处理,在不允许直接访问某些类,或需要对访问做一些特殊处理等,这时候可以考虑使用代理.目前 Java 开发包中提供了对动态代理的支持,但现在只支持对接口的实现. 主要是通过 java.lang.reflect.Proxy 类和 java.lang.reflect.InvocationHandler 接口. Proxy 类主要用来获取动态代理对象,InvocationHand

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

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

AndroidInject项目使用动态代理增加对网络请求的支持

以下内容为原创,欢迎转载,转载请注明 来自天天博客:http://www.cnblogs.com/tiantianbyconan/p/3540427.html   AndroidInject项目是我写的一个使用注解注入来简化代码的开源项目 https://github.com/wangjiegulu/androidInject 今天新增功能如下: 1. 增加@AIScreenSize注解,作用于属性,用于注入当前设备的屏幕大小(宽高)2. 增加对网络请求的支持,使用动态代理实现:@AIGet注解

java 代理模式(静态代理+动态代理)

静态代理: ISubject: /** * @author com.tiantian * @version 创建时间:2012-11-20 下午1:49:29 */ public interface ISubject { public void request(); } RealSubject(真实角色): /** * @author com.tiantian * @version 创建时间:2012-11-20 下午1:51:37 */ public class RealSubject imp

spring源码学习之【准备】jdk动态代理例子

一:被代理的对象所要实现的接口 1 package com.yeepay.testpoxy; 2 3 import java.util.Map; 4 5 /** 6 * 被动态代理的接口 7 * @author shangxiaofei 8 * 9 */ 10 public interface MyCheckPay { 11 /** 12 * 付钱的接口 13 * @param name 14 * @param money 15 * @return 16 */ 17 public Map<Str

java之架构基础-动态代理&amp;amp;cglib

本文核心主要参数动态代理和cglib: 在以前的文章中,有提及到动态代理,它要解决的就是,当我们的某些代码前面或后面都需要一些处理的时候,如写日志.事务控制.做agent.自动化代码跟踪等,此时会给你带来无限的方便,这是JVM级别的提供的一种代理机制,不过在这种机制下调用方法在JVM7出来前还没有invokeDynamic的时候,调用的效率是很低的,此时方法调用都是通过method的invoke去实现. 其基本原理是基于实现JVM提供的一个: InvocationHandler的接口,实现一个方