`
lsk569937453
  • 浏览: 6140 次
文章分类
社区版块
存档分类
最新评论

java动态代理

    博客分类:
  • java
 
阅读更多

java高级群329019348

 

1、java动态代理是通过实现InvovationHandler的invoke方法完成的。原理就是在代理类ProxyClass生成的时候把InvocationHandler当作入参传入到构造函数中,同时在静态模块中根据类名反射生成class。

 

下面一步一步揭开上述的流程。

 

 

IService service=new ServiceImp();
ProxyHandler proxyHandler=new ProxyHandler(service);
IService iService=(IService)Proxy.newProxyInstance(ServiceImp.class.getClassLoader(), ServiceImp.class.getInterfaces(),proxyHandler);

 

iService.doService();

  上述是我们的调用流程,ServiceImp实现了接口Iservice,第二行是产生一个ProxyHandler的实例,第三行是通过静态方法Proxy. newProxyInstance生成的Object强转为IService接口,第四行就是通过强转的接口来调用doService方法。

   下面来分析Proxy.newProxyInstance这个方法,源码中有这么一句

/*
         * Look up or generate the designated proxy class.
         */
        Class<?> cl = getProxyClass0(loader, intfs);

    看注释就知道这句是生成代理类的,继续往下追

 // If the proxy class defined by the given loader implementing
        // the given interfaces exists, this will simply return the cached copy;
        // otherwise, it will create the proxy class via the ProxyClassFactory
        return proxyClassCache.get(loader, interfaces);

    不懂就看注释,其实就是将代理类和ClassLoader做了一个缓存,如果缓存中找不到,就通过ProxyClassFactory创建一个代理类,那么我们重点关注一下下面源码中有ProxyClassFactory实例的地方

 // create subKey and retrieve the possible Supplier<V> stored by that
        // subKey from valuesMap
        Object subKey = Objects.requireNonNull(subKeyFactory.apply(key, parameter));

  在动态调试到这里的时候发现,paramer是需要代理的接口,而apply接口的实现类其中就有一个ProxyClassFactory,我们看一下apply内部的实现

 Map<Class<?>, Boolean> interfaceSet = new IdentityHashMap<>(interfaces.length);
            for (Class<?> intf : interfaces) {
                /*
                 * Verify that the class loader resolves the name of this
                 * interface to the same Class object.
                 */
                Class<?> interfaceClass = null;
                try {
                    interfaceClass = Class.forName(intf.getName(), false, loader);
                } catch (ClassNotFoundException e) {
                }
                if (interfaceClass != intf) {
                    throw new IllegalArgumentException(
                        intf + " is not visible from class loader");
                }
                /*
                 * Verify that the Class object actually represents an
                 * interface.
                 */
                if (!interfaceClass.isInterface()) {
                    throw new IllegalArgumentException(
                        interfaceClass.getName() + " is not an interface");
                }
                /*
                 * Verify that this interface is not a duplicate.
                 */
                if (interfaceSet.put(interfaceClass, Boolean.TRUE) != null) {
                    throw new IllegalArgumentException(
                        "repeated interface: " + interfaceClass.getName());
                }
            }

  上面对需要代理的类进行了一系列的预判断,抛出了一系列的异常,其中一个就是代理的必须是接口。如果不是接口就会抛出异常,那代理的类是怎么生成的呢?我们继续往下看,

byte[] proxyClassFile = ProxyGenerator.generateProxyClass(
                proxyName, interfaces);

  通过上面的代码,就生成了class的二进制文件。 generateProxyClass的两个参数。第一个是代理的类的名字,第二个是接口,就是和我们手动创建一个类实现接口是一个意思。本来是想继续往下看的,结果再往下看无法看到源码了,那就手动调用一次看看输出的class二进制文件长的啥样。

 

byte[]classFile= ProxyGenerator.generateProxyClass("com.newService",new Class[]{IService.class});
		File file=new File("Test.class");
		try {

			file.createNewFile();//建立输出字节流
			FileOutputStream fos = new FileOutputStream(file);
			//用FileOutputStream 的write方法写入字节数组
			fos.write(classFile);
			System.out.println("写入成功");
		}catch (Exception e)
		{
			e.printStackTrace();
		}

     反编译后的class文件如下:

    

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

package com;

import com.mfuny.proxy.IService;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.UndeclaredThrowableException;

public final class newService extends Proxy implements IService {
    private static Method m1;
    private static Method m0;
    private static Method m3;
    private static Method m2;

    public newService(InvocationHandler var1) throws  {
        super(var1);
    }

    public final boolean equals(Object var1) throws  {
        try {
            return ((Boolean)super.h.invoke(this, m1, new Object[]{var1})).booleanValue();
        } catch (RuntimeException | Error var3) {
            throw var3;
        } catch (Throwable var4) {
            throw new UndeclaredThrowableException(var4);
        }
    }

    public final int hashCode() throws  {
        try {
            return ((Integer)super.h.invoke(this, m0, (Object[])null)).intValue();
        } catch (RuntimeException | Error var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new UndeclaredThrowableException(var3);
        }
    }

     public final void doService() throws  {
        try {
            super.h.invoke(this, m3, (Object[])null);
        } catch (RuntimeException | Error var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new UndeclaredThrowableException(var3);
        }
    }

    public final String toString() throws  {
        try {
            return (String)super.h.invoke(this, m2, (Object[])null);
        } catch (RuntimeException | Error var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new UndeclaredThrowableException(var3);
        }
    }

    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.mfuny.proxy.IService").getMethod("doService", new Class[0]);
            m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]);
        } catch (NoSuchMethodException var2) {
            throw new NoSuchMethodError(var2.getMessage());
        } catch (ClassNotFoundException var3) {
            throw new NoClassDefFoundError(var3.getMessage());
        }
    }
}
   可以看到在代理类继承了Proxy类,实现了代理的接口。在静态方法里面初始化了代理的类的方法。在doService方法里调用了基类的handler的invoke方法。

 

   至此,终于真相大白了。

   在总结一下java动态代理的特点:

   1、代理类必须是接口,不是接口的话会抛出异常

   2、通过ProxyGenerator.generateProxyClass(Object[]args)生成一个类 ,第一个是类名,第二个是接口数组,传入需要代理的接口数组。就会生成一个继承自java.lang.reflect.Proxy的代理类,代理类内部实现的接口都会调用基类Proxy内的handler进行invoke操作,基类内部的InvocationHandler怎么来的呢?是通过静态方法Proxy.newProxyInstance的第三个参数传入的

  

 

分享到:
评论

相关推荐

    java动态代理demo

    Java动态代理是Java编程中一个重要的特性,它允许我们在运行时创建代理对象,这些代理对象可以代表并增强原对象的功能。动态代理在很多场景下都非常有用,比如日志记录、性能监控、事务管理等。本示例将带你深入理解...

    java动态代理实例

    Java动态代理是Java语言提供的一种在运行时创建代理对象的技术,它允许我们为已存在的接口创建代理类,以便在调用真实目标对象的方法时添加额外的功能或行为。在这个实例中,我们将深入探讨Java动态代理的核心概念,...

    java动态代理 经典文章(word 2007格式的)

    Java动态代理是Java编程中一个重要的特性,它允许在运行时创建代理对象,这些代理对象可以代表并增强原对象的功能。动态代理主要应用于面向切面编程(AOP)和事件监听等场景,使得代码更加模块化,易于维护。以下是...

    Java动态代理两种实现方式

    Java动态代理技术是Java编程中一个非常重要的特性,它允许我们在运行时动态创建具有特定行为的对象。这种技术常用于AOP(面向切面编程)和框架中,如Spring AOP,用于实现方法拦截、事务管理等功能。Java提供了两种...

    Java动态代理helloworld

    本篇文章将深入探讨Java动态代理的概念、原理以及如何通过一个简单的"Hello, World!"示例来理解它。 动态代理,顾名思义,是在程序运行时动态地生成代理对象。与静态代理(编译时已知)相比,动态代理更加灵活,...

    Java 动态代理详解(学习资料)

    JDK 动态代理JDK 提供了 java.lang.reflect.Proxy 类和 java.lang.reflect.InvocationHandler 接口来支持动态代理。Proxy 类用于创建一个代理对象,而 InvocationHandler 接口则定义了代理对象的方法调用处理逻辑。...

    java 动态代理 简单实例

    Java动态代理是Java语言提供的一种在运行时创建代理对象的技术,它允许我们为已存在的接口创建代理类,以便在调用方法时添加额外的功能或控制。动态代理在很多场景下非常有用,比如日志记录、性能监控、事务管理等。...

    java动态代理机制

    Java动态代理机制是Java语言提供的一种强大的功能,它允许在运行时创建代理对象来实现特定接口,从而可以灵活地扩展或增强已有代码的功能。在Java中,动态代理主要通过两个类来实现:`java.lang.reflect.Proxy` 和 `...

    java 动态代理实现AOP

    ### Java动态代理实现AOP详解 #### 一、引言 随着软件开发复杂度的提升,传统的面向对象编程(OOP)已经难以满足现代软件工程的需求。为了更好地管理跨切面的关注点,如日志记录、性能监控、安全控制等,面向切面...

    java动态代理和反射

    java动态代理 public class HireProxy implements InvocationHandler { //被代理的真实角色 private Object obj; public HireProxy(Object obj) { super(); this.obj = obj; } //第二个参数method,被...

    一个简单的java动态代理的实例

    Java动态代理是Java提供的一种在运行时创建代理对象的技术,主要由`java.lang.reflect.Proxy`类和`java.lang.reflect.InvocationHandler`接口组成。在这个简单的Java动态代理实例中,我们将探讨如何利用这两个核心...

    java动态代理(2)

    Java动态代理机制是Java语言提供的一种强大的功能,它允许在运行时创建代理对象来实现指定的接口。这一机制使得我们可以在不修改已有代码的情况下,为已有接口增加额外的功能或者增强已有功能的行为。在Java中,动态...

    java动态代理机制分析及拓展

    Java动态代理机制的优点在于灵活性和便捷性,它允许在运行时动态创建符合特定接口的代理对象,无需对原有代码做任何修改,使得我们可以方便地实现诸如日志、事务控制等跨切面的逻辑。不过,动态代理仅限于代理接口,...

    用Java动态代理实现AOP

    Java动态代理实现AOP Java动态代理是实现Aspect Oriented Programming(AOP)的重要手段。在Java中,动态代理可以通过java.lang.reflect InvocationHandler接口和java.lang.reflect.Proxy类来实现。AOP的主要思想...

    java动态代理(3)

    Java动态代理是Java编程中一个非常重要的特性,它允许我们在运行时创建代理对象来代替目标对象,以便在不修改原有代码的情况下对目标对象的行为进行增强或扩展。在Java.lang.reflect包下,动态代理主要涉及两个核心...

    对代理模式与Java动态代理类的理解

    对代理模式与Java动态代理类的理解说明

    基于Java动态代理和反射机制实现ORM

    总之,基于Java动态代理和反射机制实现ORM,可以有效地解耦业务逻辑和数据库操作,提高代码的可读性和可维护性。虽然现有的ORM框架如Hibernate、MyBatis已经相当成熟,但对于学习和理解Java的高级特性,这样的实践...

    Java动态代理实现数据源连接池

    Java动态代理是Java语言提供的一种机制,它允许在运行时创建一个对象的代理,这个代理对象可以在调用实际方法之前和之后添加额外的功能。在Java中,动态代理主要通过`java.lang.reflect.Proxy`类和`java.lang....

Global site tag (gtag.js) - Google Analytics