Java动态代理实现原理浅析

代码编写

  1. 接口编写

    public interface TargetInterface {

    void targetMethod();

    }

  2. 实现类编写

    public class Target implements TargetInterface {

    @Override

    public void targetMethod() {

    System.out.println("target method invoking ...");

    }

    }

  3. 增强类编写

    public class ProxyHandler implements InvocationHandler {

    private Object proxyTarget;

    public ProxyHandler(Object proxyTarget) {

    this.proxyTarget = proxyTarget;

    }

    @Override

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

    System.out.println("do somethings before target method invoke");

    Object result = method.invoke(proxyTarget, args);

    System.out.println("do somethings after target method invoke");

    return result;

    }

    }

  4. 测试类编写

    public class ProxyTest {

    public static void main(String[] args) {

    System.out.println(Thread.currentThread().getContextClassLoader());

    TargetInterface target = new Target();

    ClassLoader loader = target.getClass().getClassLoader();

    Class<?>[] interfaces = target.getClass().getInterfaces();

    InvocationHandler proxyHandler = new ProxyHandler(target);

    TargetInterface proxyTarget = (TargetInterface) Proxy.newProxyInstance(loader, interfaces, proxyHandler);

    proxyTarget.targetMethod();

    }

    }

源码分析(源码篇幅过多,省略部分由“…”表示)

代码中proxyTarget增强类是由Proxy.newProxyInstance(…)生成的,查看该方法源码:

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

...

// step1:从缓存中查找代理类,若未缓存则生成后缓存,否则直接从缓存中获取.

Class<?> cl = getProxyClass0(loader, intfs);

try {

...

//step2:反射生成代理类实例

return newInstance(cons, ih);

...

} catch (NoSuchMethodException e) {

...

}

}

代码中可以看出,代理类的生成主要分为两步:

- 生成代理类

- 反射生成代理类实例

step1:

  1. Proxy.getProxyClass0

    private static Class<?> getProxyClass0(ClassLoader loader,Class<?>... interfaces) {

    ...

    // Proxy类中维护了一个WeakCache对象,用于缓存动态生成的类,WeakCache.get方法不仅执行查找操作,当对象不存在时也会执行生成操作,下面来看下该方法的源码

    return proxyClassCache.get(loader, interfaces);

    }

  2. WeakCache.get

    public V get(K key, P parameter) {

    ...

    while (true) {

    if (supplier != null) {

    //已从缓存中查找到对象,直接返回

    V value = supplier.get();

    if (value != null) {

    return value;

    }

    }

    if (factory == null) {

    //已从缓存中查找到对象,且调用该对象的get方法生成代理类后直接返回,get方法实现下文详述

    factory = new Factory(key, parameter, subKey, valuesMap);

    }

    if (supplier == null) {

    //将新生成的对象缓存

    supplier = valuesMap.putIfAbsent(subKey, factory);

    if (supplier == null) {

    supplier = factory;

    }

    } else {

    ...

    }

    }

    }

    }

    此方法会不断的循环以及重复判断,均是在考虑线程安全问题。此处未做深究。

  3. Faotory.get

    public synchronized V get() {

    ...

    try {

    //实现生成代理类对象,此方法在内部类ProxyClassFactory中实现

    value = Objects.requireNonNull(valueFactory.apply(key, parameter));

    } finally {

    ...

    }

    ...

    return value;

    }

  4. ProxyClassFactory.apply

    public Class apply(ClassLoader loader, Class[] interfaces) {

    //校验interfaces

    ...

    String proxyPkg = null;

    ...

    //生成packagename,默认为com.sun.proxy

    if (proxyPkg == null) {

    // if no non-public proxy interfaces, use package

    proxyPkg = ReflectUtil.PROXY_PACKAGE + ".";

    }

    //生成classname,采用AutomicLong自增方式

    long num = nextUniqueNumber.getAndIncrement();

    String proxyName = proxyPkg + proxyClassNamePrefix + num;

    // 生成字节码文件

    byte[] proxyClassFile = ProxyGenerator.generateProxyClass(

    proxyName, interfaces);

    // 调用native方法,加载生成的字节码文件,并返回代理类的引用

    try {

    return defineClass0(loader, proxyName,

    proxyClassFile, 0, proxyClassFile.length);

    } catch (ClassFormatError e) {

    ...

    }

    }

    将生成的proxyClassFile字节码写入到文件并反编译后,信息如下:

package com.sun.proxy.$Proxy;

import java.lang.reflect.InvocationHandler;

import java.lang.reflect.Method;

import java.lang.reflect.Proxy;

import java.lang.reflect.UndeclaredThrowableException;

import x.constant.proxy.TargetInterface;

public final class 1 extends Proxy implements TargetInterface {

private static Method m3;

private static Method m1;

private static Method m0;

private static Method m2;

public 1(InvocationHandler paramInvocationHandler) throws {

super(paramInvocationHandler);

}

public final void targetMethod() throws {

try {

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

return;

}catch (Error|RuntimeException localError) {

throw localError;

}catch (Throwable localThrowable){

throw new UndeclaredThrowableException(localThrowable);

}

}

public final boolean equals(Object paramObject) {

...

}

public final int hashCode() {

...

}

public final String toString() throws {

...

}

static {

try {

m3 = Class.forName("x.constant.proxy.TargetInterface").getMethod("targetMethod", 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]);

return;

}catch (NoSuchMethodException localNoSuchMethodException){

throw new NoSuchMethodError(localNoSuchMethodException.getMessage());

}

catch (ClassNotFoundException localClassNotFoundException)

{

throw new NoClassDefFoundError(localClassNotFoundException.getMessage());

}

}

}

可以看到,该类位于com.sun.proxy.$Proxy包下,继承Proxy对象且实现我们自定义的TargetInterface接口;构造方法需要一个InvocationHandler对象做为参数;增强后的targetMethod方法会调用InvocationHandler对象的invoke方法。

step2

增强后的类信息已经加载到JVM中并得到了该类的引用,通过反射机制调用该类的构造方法并传入我们自定义的InvocationHandler对象做为参数,即可生成该代理类对象,此处不再做解析。

通过源代码的阅读可以发现,java动态代理的实现过程:

1. 根据Interface动态生成一个该接口的代理类,并通过调用InvocationHandler中的invoke方法的方式来实现Interface中定义的方法

2. 动态加载该代理类,并通过反射的方式获取该代理类的对象。

归根结底,其实现也是通过字节码生成ASM技术来实现的。

时间: 2024-10-07 11:01:03

Java动态代理实现原理浅析的相关文章

java高级----&gt;Java动态代理的原理

Java动态代理机制的出现,使得 Java 开发人员不用手工编写代理类,只要简单地指定一组接口及委托类对象,便能动态地获得代理类.代理类会负责将所有的方法调用分派到委托对象上反射执行,在分派执行的过程中,开发人员还可以按需调整委托类对象及其功能,这是一套非常灵活有弹性的代理框架.下面我们开始动态代理的学习. 目录导航   动态代理的简要说明 简单的Java代理 Java的动态代理 Java动态代理的原理 友情链接 动态代理的简要说明 在java的动态代理机制中,有两个重要的类或接口,一个是 In

Java动态代理简单应用

概念 代理模式是基本的设计模式之一,它是开发者为了提供额外的或不同的操作,而插入的用来代替“实际”对象的对象.这些操作通常涉及与“实际”对象的通信,因此代理通常充当着中间人的角色. Java动态代理比代理的思想更进一步,因为它可以动态地创建代理并动态地处理对代理方法的调用.在动态代理上所做的所有调用都会被重定向到单一的调用处理器(InvocationHandler)上,调用处理器的工作是揭示调用的类型并确定相应的策略. Java动态代理实现机制采用了反射的思想,有关于反射的基础知识,可以参见博客

Java动态代理 深度详解

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

java动态代理原理及解析

代理:设计模式 代理模式是一种常用的设计模式,其目的就是为其他对象提供一个代理以控制对某个真实对象的访问.代理类负责为委托类预处理消息,过滤消息并转发消息,以及进行消息被委托类执行后的后续处理. 通过代理层这一中间层,有效的控制对于真实委托类对象的直接访问,同时可以实现自定义的控制策略(Spring的AOP机制),设计上获得更大的灵活性. java动态代理的类和接口(jdk1.6源码) 1,java.lang.reflect.Proxy:动态代理机制的主类,提供一组静态方法为一组接口动态的生成对

alljoyn:基于java动态代理的RPC实现原理分析

alljoyn是由高通开源,allseen组织下,作为IOT的一个开源软件框架. 本文分析它的core部分的远程调用方法的实现过程. 以android core sdk的release版本中的simple程序为例子. (eg alljoyn-14.06.00a-android-sdk-rel\alljoyn-android\core\alljoyn-14.06.00a-rel\java\samples\simple\client) 1. 下面是一个定义为alljoyn接口,并定义了一个远程调用方

Java中动态代理实现原理深究

一.前言 笔者平时开发使用"动态代理"不多,最近在看设计模式的时候,"动态代理"又在面前晃了几次,所以这次想从源码的角度去分析动态代理的实现原理,以窥探其精妙~ 二.正文 2.1 静态代理  本文源码基于:jdk1.6.0_33 在正式剖析动态代理的源码之前,我们可以先来看看"静态代理"(就是我们普通的代理模式)的UML图: 从上图可以看出,代理类"ProxySubject"和被代理类"RealSubject&quo

JAVA 动态代理原理和实现

在 Java 中动态代理和代理都很常见,几乎是所有主流框架都用到过的知识.在面试中也是经常被提到的话题,于是便总结了本文. Java动态代理的基本原理为:被代理对象需要实现某个接口(这是前提),代理对象会拦截对被代理对象的方法调用,在其中可以全然抛弃被代理对象的方法实现而完成另外的功能,也可以在被代理对象方法调用的前后增加一些额外的功能. 动态代理可以为其他对象提供一个代理以控制对某个对象的访问. 代理类负责为委托类预处理消息,过滤消息并转发消息,以及进行消息被委托类执行后的后续处理. JDK

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

一.代理模式代理模式是常用的java设计模式,他的特征是代理类与委托类有同样的接口,代理类主要负责为委托类预处理消息.过滤消息.把消息转发给委托类,以及事后处理消息等.代理类与委托类之间通常会存在关联关系,一个代理类的对象与一个委托类的对象关联,代理类的对象本身并不真正实现服务,而是通过调用委托类的对象的相关方法,来提供特定的服务.简单的说就是,我们在访问实际对象时,是通过代理对象来访问的,代理模式就是在访问实际对象时引入一定程度的间接性,因为这种间接性,可以附加多种用途.在后面我会 解释这种间

Java动态代理原理

关于Java中的动态代理,我们首先需要了解的是一种常用的设计模式--代理模式,而对于代理,根据创建代理类的时间点,又可以分为静态代理和动态代理. 一.代理模式    代理模式是常用的java设计模式,他的特征是代理类与委托类有同样的接口,代理类主要负责为委托类预处理消息.过滤消息.把消息转发给委托类,以及事后处理消息等.代理类与委托类之间通常会存在关联关系,一个代理类的对象与一个委托类的对象关联,代理类的对象本身并不真正实现服务,而是通过调用委托类的对象的相关方法,来提供特定的服务.简单的说就是