java 动态代理的学习详解

再讲java动态代理前,先来看看代理模式。

Proxy类通过组合,对Hello类进行了增强,并对其进行了委托。

代理模式代码:

public class ProxyPattern {

interface IHello{

void say() ;

}

static class Hello implements IHello{

public void say(){

System.out.println("hello world");

}

}

static class Proxy implements IHello{

IHello iHello ;

public Proxy(IHello hello){

iHello = hello ;

}

@Override

public void say() {

System.out.println("this is proxy");   //对Hello类进行了增强

iHello.say() ;

}

}

public static void main(String[] args) {

IHello hello = new Hello() ;

IHello proxy = new Proxy(hello) ;

proxy.say() ;   // 代理类实现了实现类的委托,并对实现类进行了增强。

}

}

下面讲讲动态代理:

动态代理类DynamicProxy没有直接去写一个Proxy类,而是通过实现InvocationHandler接口。在bind()方法中通过IHello接口,类加载器,调用Proxy.newProxyInstance()方法去动态生成$Proxy0的字节码,通过jad反编译可以得到$Proxy0类,所以将Proxy.newProxyInstance()代码换成new $Proxy0(this); 也是同样的效果。此时通过bind方法得到了$Proxy0类,在invoke方法中对其进行增强,再通过$Proxy0的反射机制调用到Hello类的say方法(因为ProxyDynamic实现了IHello接口,所以在bind方法时生成的$Proxy0类也实现了IHello接口,这样便可以通过反射机制调用到Hello类的say方法),实现了代理模式。

动态代理代码:

import java.lang.reflect.Field;

import java.lang.reflect.InvocationHandler;

import java.lang.reflect.Method;

import java.lang.reflect.Proxy;

import java.util.Properties;

public class DynamicProxyTest {

interface IHello{

void say() ;

}

static class Hello implements IHello{

public void say(){

System.out.println("hello world");

}

}

static class DynamicProxy implements InvocationHandler{

Object obj ;

Object bind(Object obj){

this.obj = obj ;

System.out.println("获取ihello接口");

//          return Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(), this);

// 通过接口,实现类,生成代理类的字节码 ,反编译后就是$Proxy0类

return new $Proxy0(this);  // 等价上面那句,意思便是生成一个代理类。

}

@Override

public Object invoke(Object proxy, Method method, Object[] args)

throws Throwable {

System.out.println("welcome");

return method.invoke(obj, args);

// 从$Proxy0类中的say()方法中调用此invoke() 方法,传入的method方法正是Hello类的say()方法,通过反射机制调用Hello类的say()方法。

}

}

public static void main(String[] args) {

Field field;

try {

field = System.class.getDeclaredField("props");

field.setAccessible(true);

Properties props = (Properties) field.get(null);

props.put("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");

} catch (Exception e) {

e.printStackTrace();

}

// new DynamicProxy().bind(new Hello()) 其实是$proxy0类,实现Ihello类

IHello ihello = (IHello)new DynamicProxy().bind(new Hello());

ihello.say() ;

}

}

动态代理生成的字节码通过反编译而得到的$Proxy0类,它是通过Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(), this);生成的字节码。

// Decompiled by Jad v1.5.8e2. Copyright 2001 Pavel Kouznetsov.

// Jad home page: http://kpdus.tripod.com/jad.html

// Decompiler options: packimports(3)

import java.lang.reflect.*;

public final class $Proxy0 extends Proxy

implements DynamicProxyTest.IHello{

public $Proxy0(InvocationHandler invocationhandler){

super(invocationhandler);

}

public final void say(){

try

{

super.h.invoke(this, m3, null);

// 调用InvocationHandler实现类的invoke方法,实现代理模式;并通过反射机制调用m3方法,即Hello类的say()方法。

return;

}

catch(Error _ex) { }

catch(Throwable throwable)

{

throw new UndeclaredThrowableException(throwable);

}

}

public final boolean equals(Object obj)

{

try

{

return ((Boolean)super.h.invoke(this, m1, new Object[] {

obj

})).booleanValue();

}

catch(Error _ex) { }

catch(Throwable throwable)

{

throw new UndeclaredThrowableException(throwable);

}

return false;

}

public final int hashCode()

{

try

{

return ((Integer)super.h.invoke(this, m0, null)).intValue();

}

catch(Error _ex) { }

catch(Throwable throwable)

{

throw new UndeclaredThrowableException(throwable);

}

return 0;

}

public final String toString()

{

try

{

return (String)super.h.invoke(this, m2, null);

}

catch(Error _ex) { }

catch(Throwable throwable)

{

throw new UndeclaredThrowableException(throwable);

}

return null;

}

private static Method m3;

private static Method m1;

private static Method m0;

private static Method m2;

static

{

try

{

m3 = Class.forName("DynamicProxyTest$IHello").getMethod("say", new Class[0]);

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]);

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());

}

}

}

未完待续。。。后面将加上如何生成字节码的学习。

时间: 2024-08-03 11:21:27

java 动态代理的学习详解的相关文章

java 动态代理深度学习(Proxy,InvocationHandler),含$Proxy0源码

java 动态代理深度学习, 一.相关类及其方法: java.lang.reflect.Proxy,Proxy 提供用于创建动态代理类和实例的静态方法.newProxyInstance()返回一个指定接口的代理类实例,该接口可以将方法调用指派到指定的调用处理程序(详见api文档) java.lang.reflect.InvocationHandler,InvocationHandler 是代理实例的调用处理程序 实现的接口. invoke()在代理实例上处理方法调用并返回结果.在与方法关联的代理

什么静态/动态代理,内容详解,只要看就会懂

静态代理:自己创建代理类生成源代码再对其编译.在程序运行前代理类的.class文件就已经存在了. 动态代理: 自动:可以根据我们的真实对象接口,自动生成一个增强型代码,而不要手动创建代理类写增强逻辑 运行时:可以在代码运行时,生成这个代理类,而不需要事先把这个类写好 废话少说,直接上代码 代码设计原则: 静态代理实现: 一.创建接口 1 public interface IGamePlayer { 2 3 //登录 4 public void login(String username ,Str

详解java动态代理

生活中的代理: 比如一个明星成名了以后,是需要有一个代理的,因为太多人想找他签名,应付不来,那么这个时候代理的作用是拦截你对真正明星的访问,他可以拦截下来收点费用,再叫真正的明星过来为你签名. 程序中的代理: 1,要为已存在的多个具有相同接口的目标类的各个方法增加一些系统功能,例如,异常处理.日志.计算方法的运行时间.事务管理.等等,你准备如何做? 2,编写一个与目标类具有相同接口的代理类,代理类的每个方法调用目标类的相同方法,并在调用方法时加上系统功能的代码 下图显示了在程序中代理的调用原理(

好程序员Java教程Java动态代理机制详解

好程序员Java教程Java动态代理机制详解:在java的动态代理机制中,有两个重要的类或接口,一个是 InvocationHandler(Interface).另一个则是 Proxy(Class),这一个类和接口是实现我们动态代理所必须用到的.首先我们先来看看java的API帮助文档是怎么样对这两个类进行描述的: InvocationHandler: 1InvocationHandler is the interface implemented by the invocation handle

JAVA动态代理详解

1.什么是代理 代理模式是常用的Java 设计模式,它的特征是代理类与委托类有同样的接口,代理类主要负责为委托类预处理消息.过滤消息.把消息转发给委托类,以及事后处理消息等. 2.什么是动态代理 在程序运行时,运用反射机制动态创建代理实例对象.JDK的动态代理机制只能代理实现了接口的类,而不能实现接口的类就不能实现JDK的动态代理. 相关类与接口 java.lang.reflect.Proxy:这是 Java 动态代理机制的主类,它提供了一组静态方法来为一组接口动态地生成代理类及其对象. //

Java动态代理 深度详解

代理模式是设计模式中非常重要的一种类型,而设计模式又是编程中非常重要的知识点,特别是在业务系统的重构中,更是有举足轻重的地位.代理模式从类型上来说,可以分为静态代理和动态代理两种类型. 今天我将用非常简单易懂的例子向大家介绍动态代理的两种类型,接着重点介绍动态代理的两种实现方式(Java 动态代理和 CGLib 动态代理),最后深入剖析这两种实现方式的异同,最后说说动态代理在我们周边框架中的应用. 在开始之前,我们先假设这样一个场景:有一个蛋糕店,它们都是使用蛋糕机来做蛋糕的,而且不同种类的蛋糕

JAVA 动态代理学习记录

打算用JAVA实现一个简单的RPC框架,看完RPC参考代码之后,感觉RPC的实现主要用到了两个方面的JAVA知识:网络通信和动态代理.因此,先补补动态代理的知识.---多看看代码中写的注释 参考:Java 代理模式与动态代理类 java的动态代理机制详解 在动态代理中,首先定义一个接口,这个接口中声明的方法 是 真实类需要实现的,真实类实现该方法来提供具体的操作. public interface Subject { public abstract void request(); } publi

java动态代理学习笔记

没事的时候翻看lang.reflect包下的代码,发现有两部分内容:涉及反射和动态代理. 很多地方都可以看到动态代理的影子,只是一直没仔细看下. 在学习之前,先提出几个问题,带着问题来看代码: 1.什么是动态代理? 2.为什么使用动态代理? 3.使用它有哪些好处? 4.哪些地方需要动态代理? --------------------分隔线----------------------------- 和动态代理有关的有两个类 1.interface InvocationHandler Object

Java动态代理学习

动态代理类 Java动态代理类位于java.lang.reflect包下,一般主要涉及到以下两个类: 1.Interface InvocationHandler 该接口中仅定义了一个方法: Object invoke(Object proxy, Method method, Object[] args) 在实际使用时,第一个参数obj一般是指代理类,method是被代理的方法,如上例中的request(),args为该方法的参数数组(无参时设置为null). 这个抽象方法在代理类中动态实现. 2