`
pingwei000
  • 浏览: 60560 次
  • 性别: Icon_minigender_1
  • 来自: 北京
文章分类
社区版块
存档分类
最新评论

JDK的动态代理是如何实现的(2)?

阅读更多
Java代码
package java.lang.reflect;   
  
import java.lang.ref.Reference;   
import java.lang.ref.WeakReference;   
import java.util.Arrays;   
import java.util.Collections;   
import java.util.HashMap;   
import java.util.HashSet;   
import java.util.Map;   
import java.util.Set;   
import java.util.WeakHashMap;   
import sun.misc.ProxyGenerator;   
  
public class Proxy implements java.io.Serializable {   
  
    private static final long serialVersionUID = -2222568056686623797L;   
    private final static String proxyClassNamePrefix = "$Proxy";   
    private final static Class[] constructorParams ={ InvocationHandler.class };   
    private static Map loaderToCache = new WeakHashMap();   
    private static Object pendingGenerationMarker = new Object();   
    private static long nextUniqueNumber = 0;   
    private static Object nextUniqueNumberLock = new Object();   
    private static Map proxyClasses =Collections.synchronizedMap(new WeakHashMap());   
    protected InvocationHandler h;   
  
    private Proxy() {   
    }   
  
    protected Proxy(InvocationHandler h) {   
    this.h = h;   
    }   
  
    //关键是这个方法,正在看.   
    public static Class<?> getProxyClass(ClassLoader loader,    
                                         Class<?>... interfaces)   
    throws IllegalArgumentException   
    {   
    if (interfaces.length > 65535) {   
        throw new IllegalArgumentException("interface limit exceeded");   
    }   
    Class proxyClass = null;   
    String[] interfaceNames = new String[interfaces.length];   
    Set interfaceSet = new HashSet();   // for detecting duplicates   
    for (int i = 0; i < interfaces.length; i++) {   
        String interfaceName = interfaces[i].getName();   
        Class interfaceClass = null;   
        try {   
        interfaceClass = Class.forName(interfaceName, false, loader);   
        } catch (ClassNotFoundException e) {   
        }   
        if (interfaceClass != interfaces[i]) {   
        throw new IllegalArgumentException(   
            interfaces[i] + " is not visible from class loader");   
        }   
        if (!interfaceClass.isInterface()) {   
        throw new IllegalArgumentException(   
            interfaceClass.getName() + " is not an interface");   
        }   
        if (interfaceSet.contains(interfaceClass)) {   
        throw new IllegalArgumentException(   
            "repeated interface: " + interfaceClass.getName());   
        }   
        interfaceSet.add(interfaceClass);   
        interfaceNames[i] = interfaceName;   
    }   
    Object key = Arrays.asList(interfaceNames);   
    Map cache;   
    synchronized (loaderToCache) {   
        cache = (Map) loaderToCache.get(loader);   
        if (cache == null) {   
        cache = new HashMap();   
        loaderToCache.put(loader, cache);   
        }   
    }   
    synchronized (cache) {   
        do {   
        Object value = cache.get(key);   
        if (value instanceof Reference) {   
            proxyClass = (Class) ((Reference) value).get();   
        }   
        if (proxyClass != null) {   
            return proxyClass;   
        } else if (value == pendingGenerationMarker) {   
            try {   
            cache.wait();   
            } catch (InterruptedException e) {   
            }   
            continue;   
        } else {   
            cache.put(key, pendingGenerationMarker);   
            break;   
        }   
        } while (true);   
    }   
    try {   
        String proxyPkg = null; // package to define proxy class in   
        for (int i = 0; i < interfaces.length; i++) {   
        int flags = interfaces[i].getModifiers();   
        if (!Modifier.isPublic(flags)) {   
            String name = interfaces[i].getName();   
            int n = name.lastIndexOf('.');   
            String pkg = ((n == -1) ? "" : name.substring(0, n + 1));   
            if (proxyPkg == null) {   
            proxyPkg = pkg;   
            } else if (!pkg.equals(proxyPkg)) {   
            throw new IllegalArgumentException(   
                "non-public interfaces from different packages");   
            }   
        }   
        }   
        if (proxyPkg == null) { // if no non-public proxy interfaces,   
        proxyPkg = "";      // use the unnamed package   
        }   
        {   
        long num;   
        synchronized (nextUniqueNumberLock) {   
            num = nextUniqueNumber++;   
        }   
        String proxyName = proxyPkg + proxyClassNamePrefix + num;   
        byte[] proxyClassFile = ProxyGenerator.generateProxyClass(   
            proxyName, interfaces);   
        try {   
            proxyClass = defineClass0(loader, proxyName,   
            proxyClassFile, 0, proxyClassFile.length);   
        } catch (ClassFormatError e) {   
            throw new IllegalArgumentException(e.toString());   
        }   
        }   
        proxyClasses.put(proxyClass, null);   
    } finally {   
        synchronized (cache) {   
        if (proxyClass != null) {   
            cache.put(key, new WeakReference(proxyClass));   
        } else {   
            cache.remove(key);   
        }   
        cache.notifyAll();   
        }   
    }   
    return proxyClass;   
    }   
  
    //这个就是我的例子中调用的方法.   
    public static Object newProxyInstance(ClassLoader loader,   
                      Class<?>[] interfaces,   
                      InvocationHandler h)   
    throws IllegalArgumentException   
    {   
    if (h == null) {   
        throw new NullPointerException();   
    }   
    Class cl = getProxyClass(loader, interfaces);   
    try {   
        Constructor cons = cl.getConstructor(constructorParams);   
        return (Object) cons.newInstance(new Object[] { h });   
    } catch (NoSuchMethodException e) {   
        throw new InternalError(e.toString());   
    } catch (IllegalAccessException e) {   
        throw new InternalError(e.toString());   
    } catch (InstantiationException e) {   
        throw new InternalError(e.toString());   
    } catch (InvocationTargetException e) {   
        throw new InternalError(e.toString());   
    }   
    }   
  
  
    public static boolean isProxyClass(Class<?> cl) {   
    if (cl == null) {   
        throw new NullPointerException();   
    }   
  
    return proxyClasses.containsKey(cl);   
    }   
  
  
    public static InvocationHandler getInvocationHandler(Object proxy)   
    throws IllegalArgumentException   
    {   
  
    if (!isProxyClass(proxy.getClass())) {   
        throw new IllegalArgumentException("not a proxy instance");   
    }   
    Proxy p = (Proxy) proxy;   
    return p.h;   
    }   
  
  
    private static native Class defineClass0(ClassLoader loader, String name,   
                         byte[] b, int off, int len);   
}  
Class cl = getProxyClass(loader, interfaces);
生成实现接口的类,并自动设置一个ContractorMethodName(InvocationHandler h)的构造函数?

如果这样就还有一个问题也是最关键的问题搞不懂.

就是InvocationHandler 的invoke是如何被调用的?是对代理接口的每个声明的方法生成类似如下代码?

Java代码
makeCar()   
{   
   handler.invoke(......);   
}  

分享到:
评论

相关推荐

    浅谈JDK动态代理与CGLIB代理去区别

    JDK动态代理的局限性在于,它只能为实现了至少一个接口的类创建代理,因为代理对象必须继承自这些接口。这种方式适用于那些基于接口进行编程的设计,比如Spring AOP中的Advisor和Advice。 相反,CGLIB(Code ...

    JDK动态代理_JDK动态代理

    ### JDK动态代理详解 #### 一、引言 在软件工程中,代理模式是一种常见的设计模式,它通过为一个对象提供一个替代品或占位符来控制对这个对象的访问。这种模式通常用于添加额外的功能(例如日志记录、事务管理等)...

    关于jdk动态代理的源码剖析

    - **只能代理实现了接口的类**:这是JDK动态代理的一个限制,如果目标对象没有实现任何接口,则无法使用JDK动态代理。 - **性能开销**:虽然这种开销通常很小,但在高并发场景下可能会成为瓶颈。 通过上述分析,...

    Spring框架中JDK动态代理和cglib动态代理

    如果我们想使用 JDK 动态代理,必须提供一个接口,并且将其实现类交给 JDK 动态代理来生成代理类。 CGLIB 动态代理是基于类的代理, 它可以代理类和接口。CGLIB 动态代理使用 ASM 字节码工具来生成代理类。CGLIB ...

    模拟JDK动态代理内部实现

    在本文中,我们将深入探讨如何模拟JDK的动态代理内部实现。 首先,我们需要了解JDK动态代理的基础知识。Java中的动态代理通过`java.lang.reflect.Proxy`类和`java.lang.reflect.InvocationHandler`接口实现。`Proxy...

    jdk动态代理技术详解

    JDK 动态代理技术是 Java 语言自身对动态代理的支持,提供了一种灵活和高效的方式来实现动态代理。通过使用 InvocationHandler 接口和 Proxy 类,可以轻松地实现动态代理,提高软件的灵活性和扩展性。

    JDK动态代理源码

    在Java编程领域,JDK动态代理是一个非常重要的概念,它允许我们在运行时动态地创建一个实现了特定接口的代理对象,以此来拦截并扩展原有对象的行为。动态代理在很多场景下都有应用,比如AOP(面向切面编程)、事件...

    JDK动态代理简单示例

    除了基本的代理实现,JDK动态代理还可以结合其他设计模式,如工厂模式,创建更加复杂的代理对象。此外,Spring框架中的AOP功能也是基于JDK动态代理或CGLIB实现的,它允许开发者定义切面,对满足特定条件的方法进行...

    JDK动态代理 spring aop 的原理

    在Java编程领域,JDK动态代理是实现动态创建代理对象的一种技术,它是Java标准库提供的一种强大工具。Spring AOP(面向切面编程)则是一种流行的应用框架,它利用动态代理来实现对业务代码的切面增强,如日志、事务...

    AOP之JDK动态代理和CGLib动态代理

    Spring框架是AOP实现的一个典范,它提供了两种主要的动态代理方式:JDK动态代理和CGLib动态代理。 **JDK动态代理**: JDK动态代理基于Java的反射API实现,适用于接口代理。当目标对象实现了至少一个接口时,Spring...

    java-jdk动态代理的实现demo

    Java JDK 动态代理是一种强大的特性,它允许我们在运行时创建代理类,这些代理类可以扩展或修饰已存在的接口实现。动态代理在很多场景下非常有用,比如日志记录、性能监控、事务管理等,这些功能可以在不修改原始...

    jdk动态代理和CGlib动态代理

    JDK动态代理和CGlib动态代理是Java中实现这一目标的两种主要方式。 ### JDK动态代理 JDK动态代理基于Java的接口实现。如果一个类实现了至少一个接口,我们就可以为这个类创建一个动态代理。动态代理通过`java.lang....

    jdk动态代理 + 拦截器实现小例

    在这个“jdk动态代理 + 拦截器实现小例”中,我们将探讨如何利用Java的InvocationHandler接口和Proxy类来实现拦截器模式,以实现灵活的代码扩展和日志记录、性能监控等需求。 首先,让我们理解什么是动态代理。在...

    java代理机制 JDK动态代理和cglib代理 详解

    本文将深入探讨两种主要的Java代理实现:JDK动态代理和CGLIB代理。 一、JDK动态代理 JDK动态代理基于接口实现,它要求被代理的类必须实现至少一个接口。在运行时,Java会动态地创建一个新的类,这个类实现了与原始...

    代理模式,JDK动态代理,SpringAOP来龙去脉

    在Java中,我们可以使用JDK的动态代理或者Spring AOP来实现代理模式。 JDK动态代理主要依赖于`java.lang.reflect.Proxy`类和`java.lang.reflect.InvocationHandler`接口。Proxy类是生成代理对象的工厂,而...

    spring jdk动态代理

    Spring AOP允许我们通过代理来实现横切关注点,如日志、事务管理等,而JDK动态代理则是Spring AOP实现的一种方式。本文将深入探讨Spring如何利用JDK动态代理技术来实现这一功能,并通过实例解析其底层实现。 首先,...

    JDK动态代理和CGLIB代理

    这种代理方式适用于目标对象实现了特定接口的情况,因为JDK动态代理只能代理实现了接口的类。 以下是一个简单的JDK动态代理示例: ```java interface MyService { void doSomething(); } class MyServiceImpl ...

    Jdk动态代理和cglib动态代理原理

    - **JDK代理**适用于目标类实现有接口的情况,更符合面向接口的设计原则,且无需引入额外的库。 - **CGLIB代理**适用于目标类没有接口或者不希望修改原有接口的情况,其性能通常优于JDK代理,因为它是基于字节码生成...

    java jdk 动态代理 演示demo

    Java JDK 动态代理是一种强大的特性,它允许我们在运行时创建代理对象,这些代理对象可以扩展或增强已存在的接口实现。动态代理在处理AOP(面向切面编程)场景、事件监听、性能监控等方面有着广泛的应用。下面我们将...

Global site tag (gtag.js) - Google Analytics