为什么80%的码农都做不了架构师?>>>   

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

一  业务接口类
public interface BusinessProcessor {
 public void processBusiness();
}
二 业务实现类
public class BusinessProcessorImpl implements BusinessProcessor {
 public void processBusiness() {
  System.out.println("processing business.....");
 }
}

三 业务代理类
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

public class BusinessProcessorHandler implements InvocationHandler {
 private Object target = null;
 BusinessProcessorHandler(Object target){
  this.target = target;
 }

public Object invoke(Object proxy, Method method, Object[] args)
   throws Throwable {
  System.out.println("You can do something here before process your business");
  Object result = method.invoke(target, args);
  System.out.println("You can do something here after process your business");
  return result;
 }

}

四 客户端应用类
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.Proxy;

public class Test {

public static void main(String[] args) {
  BusinessProcessorImpl bpimpl = new BusinessProcessorImpl();
  BusinessProcessorHandler handler = new BusinessProcessorHandler(bpimpl);
  BusinessProcessor bp = (BusinessProcessor)Proxy.newProxyInstance(bpimpl.getClass().getClassLoader(), bpimpl.getClass().getInterfaces(), handler);
  bp.processBusiness();
 }
}

现在我们看一下打印结果:

You can do something here before process your business
processing business.....
You can do something here after process your business

通过结果我们就能够很简单的看出Proxy的作用了,它能够在你的核心业务方法前后做一些你所想做的辅助工作,如log日志,安全机制等等。

现在我们来分析一下上面的类的工作原理。

类一二没什么好说的。先看看类三吧。 实现了InvocationHandler接口的invoke方法。其实这个类就是最终Proxy调用的固定接口方法。Proxy不管客户端的业务方法是怎么实现的。当客户端调用Proxy时,它只

会调用InvocationHandler的invoke接口,所以我们的真正实现的方法就必须在invoke方法中去调用。关系如下:

BusinessProcessorImpl bpimpl = new BusinessProcessorImpl();
 BusinessProcessorHandler handler = new BusinessProcessorHandler(bpimpl);

BusinessProcessor bp = (BusinessProcessor)Proxy.newProxyInstance(....);

bp.processBusiness()-->invocationHandler.invoke()-->bpimpl.processBusiness();

那么bp到底是怎么样一个对象呢。我们改一下main方法看一下就知道了:

public static void main(String[] args) {
  BusinessProcessorImpl bpimpl = new BusinessProcessorImpl();
  BusinessProcessorHandler handler = new BusinessProcessorHandler(bpimpl);
  BusinessProcessor bp = (BusinessProcessor)Proxy.newProxyInstance(bpimpl.getClass().getClassLoader(), bpimpl.getClass().getInterfaces(), handler);
  bp.processBusiness();
  System.out.println(bp.getClass().getName());
 }

输出结果:

You can do something here before process your business
processing business.....
You can do something here after process your business
$Proxy0

bp原来是个$Proxy0这个类的对象。那么这个类到底是长什么样子呢?好的。我们再写二个方法去把这个类打印出来看个究竟,是什么三头六臂呢?我们在main下面写如下两个静态方法。

public static String getModifier(int modifier){
  String result = "";
  switch(modifier){
   case Modifier.PRIVATE:
    result = "private";
   case Modifier.PUBLIC:
    result = "public";
   case Modifier.PROTECTED:
    result = "protected";
   case Modifier.ABSTRACT :
    result = "abstract";
   case Modifier.FINAL :
    result = "final";
   case Modifier.NATIVE :
    result = "native";
   case Modifier.STATIC :
    result = "static";
   case Modifier.SYNCHRONIZED :
    result = "synchronized";
   case Modifier.STRICT  :
    result = "strict";
   case Modifier.TRANSIENT :
    result = "transient";
   case Modifier.VOLATILE :
    result = "volatile";
   case Modifier.INTERFACE :
    result = "interface";
  }
  return result;
 }
 
 public static void printClassDefinition(Class clz){

Constructor[] cons=clz.getConstructors();

if(null!=cons  && cons.length>0){

for(Constructor con:cons){

System.out.println(con);

}

}

String clzModifier = getModifier(clz.getModifiers());
  if(clzModifier!=null && !clzModifier.equals("")){
   clzModifier = clzModifier + " ";
  }
  String superClz = clz.getSuperclass().getName();
  if(superClz!=null && !superClz.equals("")){
   superClz = "extends " + superClz;
  }
  
  Class[] interfaces = clz.getInterfaces();
  
  String inters = "";
  for(int i=0; i<interfaces.length; i++){
   if(i==0){
    inters += "implements ";
   }
   inters += interfaces[i].getName();
  }
  
  System.out.println(clzModifier +clz.getName()+" " + superClz +" " + inters );
  System.out.println("{");
  
  Field[] fields = clz.getDeclaredFields();
  for(int i=0; i<fields.length; i++){
   String modifier = getModifier(fields[i].getModifiers());
   if(modifier!=null && !modifier.equals("")){
    modifier = modifier + " ";
   }
   String fieldName = fields[i].getName();
   String fieldType = fields[i].getType().getName();
   System.out.println("    "+modifier + fieldType + " "+ fieldName + ";");
  }
  
  System.out.println();
  
  Method[] methods = clz.getDeclaredMethods();
  for(int i=0; i<methods.length; i++){
   Method method = methods[i];

String modifier = getModifier(method.getModifiers());
   if(modifier!=null && !modifier.equals("")){
    modifier = modifier + " ";
   }
   
   String methodName = method.getName();
   
   Class returnClz = method.getReturnType();
   String retrunType = returnClz.getName();
   
   Class[] clzs = method.getParameterTypes();
   String paraList = "(";
   for(int j=0; j<clzs.length; j++){
    paraList += clzs[j].getName();
    if(j != clzs.length -1 ){
     paraList += ", ";
    }
   }
   paraList += ")";
   
   clzs = method.getExceptionTypes();
   String exceptions = "";
   for(int j=0; j<clzs.length; j++){
    if(j==0){
     exceptions += "throws ";
    }

exceptions += clzs[j].getName();
    
    if(j != clzs.length -1 ){
     exceptions += ", ";
    }
   }
   
   exceptions += ";";
   
   String methodPrototype = modifier +retrunType+" "+methodName+paraList+exceptions;
   
   System.out.println("    "+methodPrototype );
   
  }
  System.out.println("}");
 }

再改写main方法

public static void main(String[] args) {
  BusinessProcessorImpl bpimpl = new BusinessProcessorImpl();
  BusinessProcessorHandler handler = new BusinessProcessorHandler(bpimpl);
  BusinessProcessor bp = (BusinessProcessor)Proxy.newProxyInstance(bpimpl.getClass().getClassLoader(), bpimpl.getClass().getInterfaces(), handler);
  bp.processBusiness();
  System.out.println(bp.getClass().getName());
  Class clz = bp.getClass();
  printClassDefinition(clz);
 }

现在我们再看看输出结果:

You can do something here before process your business
processing business.....
You can do something here after process your business
$Proxy0
$Proxy0 extends java.lang.reflect.Proxy implements com.tom.proxy.dynamic.BusinessProcessor
{
    java.lang.reflect.Method m4;
    java.lang.reflect.Method m2;
    java.lang.reflect.Method m0;
    java.lang.reflect.Method m3;
    java.lang.reflect.Method m1;

void processBusiness();
    int hashCode();
    boolean equals(java.lang.Object);
    java.lang.String toString();
}

很明显,Proxy.newProxyInstance方法会做如下几件事:

1,根据传入的第二个参数interfaces动态生成一个类,实现interfaces中的接口,该例中即BusinessProcessor接口的processBusiness方法。并且继承了Proxy类,重写了hashcode,toString,equals等三个方法。具体实现可参看 ProxyGenerator.generateProxyClass(...); 该例中生成了$Proxy0类

2,通过传入的第一个参数classloder将刚生成的类加载到jvm中。即将$Proxy0类load

3,利用第三个参数,调用$Proxy0的$Proxy0(InvocationHandler)构造函数 创建$Proxy0的对象,并且用interfaces参数遍历其所有接口的方法,并生成Method对象初始化对象的几个Method成员变量

4,将$Proxy0的实例返回给客户端。

现在好了。我们再看客户端怎么调就清楚了。

1,客户端拿到的是$Proxy0的实例对象,由于$Proxy0实现了BusinessProcessor,因此转化为BusinessProcessor没任何问题。

BusinessProcessor bp = (BusinessProcessor)Proxy.newProxyInstance(....);

2,bp.processBusiness();

实际上调用的是$Proxy0.processBusiness();那么$Proxy0.processBusiness()的实现就是通过InvocationHandler去调用invoke方法啦!

转载于:https://my.oschina.net/milne/blog/492367

深入理解Java Proxy机制相关推荐

  1. java事件处理模型_从零开始理解JAVA事件处理机制(3)

    我们连续写了两小节的教师-学生的例子,必然觉得无聊死了,这样的例子我们就是玩上100遍,还是不知道该怎么写真实的代码.那从本节开始,我们开始往真实代码上面去靠拢. 事件最容易理解的例子是鼠标事件:我们 ...

  2. 从零开始理解JAVA事件处理机制(3)

    我们连续写了两小节的教师-学生的例子,必然觉得无聊死了,这样的例子我们就是玩上100遍,还是不知道该怎么写真实的代码.那从本节开始,我们开始往真实代码上面去靠拢. 事件最容易理解的例子是鼠标事件:我们 ...

  3. 理解Java ClassLoader机制 |用Java说话,人气战胜时间!Come On

    理解Java ClassLoader机制 |用Java说话,人气战胜时间!Come On 我在参加一个比赛. 欢迎大家都来我的网站参观一下. http://home.fego.cn/members/l ...

  4. 秒懂系列,深入理解Java反射机制

    文章目录 深入理解Java反射机制 一.Java反射概述 二.Java创建对象思想传递 三.类对象 3.1 类对象和类的对象 3.2 三种获取类对象的方法 四.Class对象的常用方法 4.1 获取成 ...

  5. 理解Java反射机制

    理解Java反射机制 1. 概述 2. 反射原理 3. 反射的优缺点 4. 反射的用途 5. 反射相关的类 5.1 Constructor 5.2 Field 5.3 Method 5.4 Class ...

  6. 深入理解Java Proxy和CGLIB动态代理原理

    点击上方关注,每天进步一点点 动态代理在Java中有着广泛的应用,比如Spring AOP,Hibernate数据查询.测试框架的后端mock.RPC,Java注解对象获取等.静态代理的代理关系在编译 ...

  7. 全面理解java异常机制

    在理想状态下,程序会按照我们预想的步骤一步一步的执行,但是即使你是大牛,你也不可避免出错,所以java为我们提供了异常机制.本文将会从以下几个方面介绍java中的异常机制: 异常机制的层次结构 异常的 ...

  8. java异常机制_全面理解java异常机制

    在理想状态下,程序会按照我们预想的步骤一步一步的执行,但是即使你是大牛,你也不可避免出错,所以java为我们提供了异常机制.本文将会从以下几个方面介绍java中的异常机制: 异常机制的层次结构 异常的 ...

  9. 深入理解java反射机制

    一,java的核心机制 java有两种核心机制:java虚拟机(JavaVirtual Machine)与垃圾收集机制(Garbage collection): Java虚拟机:是运行所有Java程序 ...

最新文章

  1. python语音转文字源码_【python3】Python十行代码搞定文字转语音
  2. 学python有必要买书吗-终于明白python需要学什么
  3. 如果去掉数学前后的空格_理综+数学+地理+英语完型的方法和技巧
  4. boost::histogram::accumulators::mean用法的测试程序
  5. windows下php7安装redis扩展
  6. 下面不是mysql特性_下面( )不是MySQL的特性。_学小易找答案
  7. 九江机器人餐厅_机器人精通200道佳肴 九江学院来了多位机器厨神
  8. 【BZOJ】1901: Zju2112 Dynamic Rankings(区间第k小+树状数组套主席树)
  9. 比特币的密钥、地址、钱包
  10. 呼叫中心职场EQ与情绪压力管控(时刻提醒自己!)
  11. uva10817 dijkstra
  12. Matlab题目及答案,Matlab考试试题库+答案解析.doc
  13. 封装Selenium2Library
  14. discuz论坛,discuz论坛程序,discuz论坛快速搭建
  15. Vue安装及环境配置、开发工具
  16. 简历推荐_5位AI产品经理
  17. Raptor制作猜数游戏流程图
  18. 万豪国际扩大北京奢华酒店布局,JW万豪将落户东城区
  19. Hadoop3.2.0 YARN资源配置
  20. UWB实现手榴弹投掷训练保护装置

热门文章

  1. Windows 命令模式下删除驱动
  2. 软件部署在不同linux上,如何在Linux中安装和部署keepalived
  3. 20200329:K 个一组翻转链表(leetcode25)
  4. dataframe 如何增加新的索引_带你领略pandas中多表之间如何处理
  5. 冯诺依曼结构和哈佛结构01
  6. 深入Scripting Runtime Library
  7. 心情随笔(四):重新审视自我
  8. 用英伟达Jetson Nano运行PyTorch Fast.ai丨手把手教程+第三方工具
  9. 10亿美元:MIT宣布建立计算学院,近70年来最大结构变革只为AI
  10. 报告 | 73%的“落伍”开发者说:明年要学AI技术