java 动态代理深度学习,

一.相关类及其方法:

java.lang.reflect.Proxy,
Proxy 提供用于创建动态代理类和实例的静态方法.
newProxyInstance()
返回一个指定接口的代理类实例,该接口可以将方法调用指派到指定的调用处理程序
(详见api文档)

java.lang.reflect.InvocationHandler,
InvocationHandler 是代理实例的调用处理程序 实现的接口。 
invoke()
在代理实例上处理方法调用并返回结果。在与方法关联的代理实例上调用方法时,将在调用处理程序上调用此方法。
(详见api文档)

二.源代码:

被代理对象的接口及实现类:
package com.ml.test;

public interface Manager {
public void modify();
}

package com.ml.test;

public class ManagerImpl implements Manager {

@Override
public void modify() {
   System.out.println("*******modify()方法被调用");
}
}

业务代理类:
package com.ml.test;

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

public class BusinessHandler implements InvocationHandler {

private Object object = null;

public BusinessHandler(Object object) {
   this.object = object;
}

@Override
public Object invoke(Object proxy, Method method, Object[] args)
    throws Throwable {
   System.out.println("do something before method");
   Object ret = method.invoke(this.object, args);
   System.out.println("do something after method");
   return ret;

}
}

客户端类:
package com.ml.test;
import java.lang.reflect.Proxy;
public class Client {

public static void main(String[] args) {
   // 元对象(被代理对象)
   ManagerImpl managerImpl = new ManagerImpl();

// 业务代理类
   BusinessHandler securityHandler = new BusinessHandler(managerImpl);

// 获得代理类($Proxy0 extends Proxy implements Manager)的实例.
   Manager managerProxy = (Manager) Proxy.newProxyInstance(managerImpl
     .getClass().getClassLoader(), managerImpl.getClass()
     .getInterfaces(), securityHandler);

managerProxy.modify();
}
}

三.执行结果:
do something before method
*******modify()方法被调用
do something after method

四.机制分析:

Proxy.(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)做了以下几件事.
(1)根据参数loader和interfaces调用方法 getProxyClass(loader, interfaces)创建代理类$Proxy.
$Proxy0类实现了interfaces的接口,并继承了Proxy类.
(2)实例化$Proxy0并在构造方法中把BusinessHandler传过去,接着$Proxy0调用父类Proxy的构造器,为h赋值,如下:
class Proxy{
   InvocationHandler h=null;
   protected Proxy(InvocationHandler h) {
    this.h = h;
   }
   ...
}

下面是本例的$Proxy0类的源码(好不容易才把它提出来):

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

public final class $Proxy0 extends Proxy implements Manager {

private static Method m1;
private static Method m0;
private static Method m3;
private static Method m2;

static {
   try {
    m1 = Class.forName("java.lang.Object").getMethod("equals",
      new Class[] { Class.forName("java.lang.Object") });
    m0 = Class.forName("java.lang.Object").getMethod("hashCode",
      new Class[0]);
    m3 = Class.forName("com.ml.test.Manager").getMethod("modify",
      new Class[0]);
    m2 = Class.forName("java.lang.Object").getMethod("toString",
      new Class[0]);
   } catch (NoSuchMethodException nosuchmethodexception) {
    throw new NoSuchMethodError(nosuchmethodexception.getMessage());
   } catch (ClassNotFoundException classnotfoundexception) {
    throw new NoClassDefFoundError(classnotfoundexception.getMessage());
   }
}

public $Proxy0(InvocationHandler invocationhandler) {
   super(invocationhandler);
}

@Override
public final boolean equals(Object obj) {
   try {
    return ((Boolean) super.h.invoke(this, m1, new Object[] { obj }))
      .booleanValue();
   } catch (Throwable throwable) {
    throw new UndeclaredThrowableException(throwable);
   }
}

@Override
public final int hashCode() {
   try {
    return ((Integer) super.h.invoke(this, m0, null)).intValue();
   } catch (Throwable throwable) {
    throw new UndeclaredThrowableException(throwable);
   }
}

public final void modify() {
   try {
    super.h.invoke(this, m3, null);
    return;
   } catch (Error e) {
   } catch (Throwable throwable) {
    throw new UndeclaredThrowableException(throwable);
   }
}

@Override
public final String toString() {
   try {
    return (String) super.h.invoke(this, m2, null);
   } catch (Throwable throwable) {
    throw new UndeclaredThrowableException(throwable);
   }
}
}

接着把得到的$Proxy0实例强制转换成Manager.
当执行managerProxy.modify()方法时,就调用了$Proxy0类中的modify()方法.
在modify方法中,调用父类Proxy中的h的invoke()方法.
即InvocationHandler.invoke();

java 动态代理深度学习(Proxy,InvocationHandler),含$Proxy0源码的更多相关文章

  1. java动态代理基本原理及proxy源码分析一

    本系列文章主要是博主在学习spring aop的过程中了解到其使用了java动态代理,本着究根问底的态度,于是对java动态代理的本质原理做了一些研究,于是便有了这个系列的文章 为了尽快进入正题,这里 ...

  2. java动态代理——jvm指令集基本概念和方法字节码结构的进一步探究及proxy源码分析四

    前文地址 https://www.cnblogs.com/tera/p/13336627.html 本系列文章主要是博主在学习spring aop的过程中了解到其使用了java动态代理,本着究根问底的 ...

  3. Java动态代理 深度详解

    代理模式是设计模式中非常重要的一种类型,而设计模式又是编程中非常重要的知识点,特别是在业务系统的重构中,更是有举足轻重的地位.代理模式从类型上来说,可以分为静态代理和动态代理两种类型. 今天我将用非常 ...

  4. java 动态代理(模式) InvocationHandler(为类中方法执行前或后添加内容)

    动态代理属于Java反射的一种. 当我们得到一个对象,想动态的为其一些方法每次被调用前后追加一些操作时,我们将会用到java动态代理. 下边上代码: 首先定义一个接口: package com.liu ...

  5. 【神经网络与深度学习】DCGAN及其TensorFlow源码

    上一节我们提到G和D由多层感知机定义.深度学习中对图像处理应用最好的模型是CNN,那么如何把CNN与GAN结合?DCGAN是这方面最好的尝试之一.源码:https://github.com/Newmu ...

  6. Java显式锁学习总结之六:Condition源码分析

    概述 先来回顾一下java中的等待/通知机制 我们有时会遇到这样的场景:线程A执行到某个点的时候,因为某个条件condition不满足,需要线程A暂停:等到线程B修改了条件condition,使con ...

  7. Java显式锁学习总结之五:ReentrantReadWriteLock源码分析

    概述 我们在介绍AbstractQueuedSynchronizer的时候介绍过,AQS支持独占式同步状态获取/释放.共享式同步状态获取/释放两种模式,对应的典型应用分别是ReentrantLock和 ...

  8. Java显式锁学习总结之四:ReentrantLock源码分析

    概述 ReentrantLock,即重入锁,是一个和synchronized关键字等价的,支持线程重入的互斥锁.只是在synchronized已有功能基础上添加了一些扩展功能. 除了支持可中断获取锁. ...

  9. java动态代理实现与原理详细分析

    关于Java中的动态代理,我们首先需要了解的是一种常用的设计模式--代理模式,而对于代理,根据创建代理类的时间点,又可以分为静态代理和动态代理. 一.代理模式    代理模式是常用的java设计模式, ...

随机推荐

  1. [RxJS] Combination operator: combineLatest

    While merge is an OR-style combination operator, combineLatest is an AND-style combination operator. ...

  2. 关于C++的疑问剖析

    1)众所周知,抽象类是不存在对象的,只提供接口而不提供实现.但是抽象类能不能作为一个类指针,指向其子类的对象呢? class Interface { public: ; }; class Implem ...

  3. Java基础知识强化之集合框架笔记24:ArrayList存储自定义对象并遍历

    1. ArrayList存储自定义对象并遍历 2. 代码示例: Student.java,如下: package cn.itcast_01; public class Student { privat ...

  4. asp.net 的脚本

    asp.net的 Web 控件有时会包装一些用户端脚本 (client-side scripting),在控件被绘制时输出到用户端,这些脚本多数被包装在 DLL 的资源档中,并由 ScriptReso ...

  5. 把nc v6的源码看懂

    看懂nc v6的源码! 碧桂园全部的正式环境的补丁都在我手里. 2015-11-18 2:33 谢谢两位一起努力的兄弟 谢谢超哥,谢谢祈冰哥,谢谢连老师,陈明大哥,谢谢龙哥,珍玉,谢谢廖生哥,谢谢林春 ...

  6. js实现图片自动切换效果。

    js实现图片自动切换效果,简单实用,原谅我只是一只小菜鸟还在学大神天天写博文装逼. <script language="javascript"> setInterval ...

  7. ab安装和使用

    apache bench(专门用于 HTTP Server .单url).win8: 下载地址:http://httpd.apache.org/download.cgi#apache24 安装apac ...

  8. Spring MVC返回json数据给Android端

    原先做Android项目时,服务端接口一直是别人写的,自己拿来调用一下,但下个项目,接口也要自己搞定了,我想用Spring MVC框架来提供接口,这两天便抽空浅学了一下该框架以及该框架如何返回json ...

  9. session marked for kill处理oracle中杀不掉的锁

    ora-00031:session marked for kill处理oracle中杀不掉的锁   一些ORACLE中的进程被杀掉后,状态被置为"killed",但是锁定的资源很长 ...

  10. awr相关指标解析

    awr相关指标解析 2016年11月11日 15:09