JDK动态代理分析

动态代理的使用

Proxy 提供用于创建动态代理类和实例的静态方法,它还是由这些方法创建的所有动态代理类的超类。

创建某一接口 Foo 的代理:

     InvocationHandler handler = new MyInvocationHandler(...);
     Class proxyClass = Proxy.getProxyClass(
         Foo.class.getClassLoader(), new Class[] { Foo.class });
     Foo f = (Foo) proxyClass.
         getConstructor(new Class[] { InvocationHandler.class }).
         newInstance(new Object[] { handler });

或使用以下更简单的方法:

     Foo f = (Foo) Proxy.newProxyInstance(Foo.class.getClassLoader(),
                                          new Class[] { Foo.class },
                                          handler);

来看一个具体的列子使用

业务代码

public interface IPersonService {
	void sayHello();
}
public class PersonServiceImpl implements IPersonService {
	@Override
	public void sayHello() {
		System.out.println("hello to you");
	}
}

增强代码实现

public class InvocationHandlerImpl implements InvocationHandler {
	
	private IPersonService service;
	
	public InvocationHandlerImpl(IPersonService service) {
		this.service = service;
	}

	@Override
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		System.out.println("==>");
		System.out.println("====>");
		Object invoke = method.invoke(service, args);
		System.out.println("======>");
		System.out.println("========>");
		return invoke;
	}
}

测试

public class Test {
	public static void main(String[] args) throws Exception {
		IPersonService service = new PersonServiceImpl();
		InvocationHandler h = new InvocationHandlerImpl(service);
		Class<?> proxyClass = Proxy.getProxyClass(service.getClass().getClassLoader(), service.getClass().getInterfaces());
		IPersonService proxyService = (IPersonService) proxyClass.getConstructor(InvocationHandler.class).newInstance(h);
		proxyService.sayHello();
	}
}

输出结果,增强代理成功

==>
====>
hello to you
======>
========>
深度分析

分析测试方法

		IPersonService service = new PersonServiceImpl();
		InvocationHandler h = new InvocationHandlerImpl(service);
		Class<?> proxyClass = Proxy.getProxyClass(service.getClass().getClassLoader(), service.getClass().getInterfaces());
		IPersonService proxyService = (IPersonService) proxyClass.getConstructor(InvocationHandler.class).newInstance(h);
		proxyService.sayHello();

从测试代码中我们可以看出,调用代码proxyService.sayHello()中的对象proxyService,是第三行代码中的proxyClass返回的对象。对应方法为Proxy.getProxyClass, 那我们查看方法getProxyClass

省略一些代码,我们可以看到是方法ProxyGenerator.generateProxyClass做了一个代理类的生成,返回值的一个代理文件的字节数组,那么我们可以将这个字节数组输出为文件看看是什么

            /*
             * Generate the specified proxy class.
             */
            byte[] proxyClassFile = ProxyGenerator.generateProxyClass(
                proxyName, interfaces, accessFlags);
            try {
                return defineClass0(loader, proxyName,
                                    proxyClassFile, 0, proxyClassFile.length);
            } catch (ClassFormatError e) {
                throw new IllegalArgumentException(e.toString());
            }

修改测试代码

public class MainTest {
	public static void main(String[] args) throws Exception {
        int accessFlags = Modifier.PUBLIC | Modifier.FINAL;
		IPersonService service = new PersonServiceImpl();
		byte[] proxyClassBytes = ProxyGenerator.generateProxyClass("$ProxyClass",
				service.getClass().getInterfaces(), accessFlags);
		FileOutputStream fos = new FileOutputStream(new File("C:\\Users\\EDENJIL\\Desktop\\bb\\$ProxyClass.class"));
		fos.write(proxyClassBytes);
		fos.flush();
		fos.close();
	}
}

生成了文件$ProxyClass.class

在这里插入图片描述
使用JD-GUI反编译工具查看,我们可以发现java动态代理,使用了字节重组技术,生成了新的代理类$ProxyClass,代理类实现了接口IPersonService

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.UndeclaredThrowableException;
import priv.dengjili.spring.design.day01.proxy.IPersonService;

public final class $ProxyClass extends Proxy implements IPersonService {
  private static Method m1;
  
  private static Method m3;
  
  private static Method m2;
  
  private static Method m0;
  
  public $ProxyClass(InvocationHandler paramInvocationHandler) {
    super(paramInvocationHandler);
  }
  
  public final boolean equals(Object paramObject) {
    try {
      return ((Boolean)this.h.invoke(this, m1, new Object[] { paramObject })).booleanValue();
    } catch (Error|RuntimeException error) {
      throw null;
    } catch (Throwable throwable) {
      throw new UndeclaredThrowableException(throwable);
    } 
  }
  
  public final void sayHello() {
    try {
      this.h.invoke(this, m3, null);
      return;
    } catch (Error|RuntimeException error) {
      throw null;
    } catch (Throwable throwable) {
      throw new UndeclaredThrowableException(throwable);
    } 
  }
  
  public final String toString() {
    try {
      return (String)this.h.invoke(this, m2, null);
    } catch (Error|RuntimeException error) {
      throw null;
    } catch (Throwable throwable) {
      throw new UndeclaredThrowableException(throwable);
    } 
  }
  
  public final int hashCode() {
    try {
      return ((Integer)this.h.invoke(this, m0, null)).intValue();
    } catch (Error|RuntimeException error) {
      throw null;
    } catch (Throwable throwable) {
      throw new UndeclaredThrowableException(throwable);
    } 
  }
  
  static {
    try {
      m1 = Class.forName("java.lang.Object").getMethod("equals", new Class[] { Class.forName("java.lang.Object") });
      m3 = Class.forName("priv.dengjili.spring.design.day01.proxy.IPersonService").getMethod("sayHello", new Class[0]);
      m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]);
      m0 = Class.forName("java.lang.Object").getMethod("hashCode", new Class[0]);
      return;
    } catch (NoSuchMethodException noSuchMethodException) {
      throw new NoSuchMethodError(noSuchMethodException.getMessage());
    } catch (ClassNotFoundException classNotFoundException) {
      throw new NoClassDefFoundError(classNotFoundException.getMessage());
    } 
  }
}

接着我们分析代码

		IPersonService proxyService = (IPersonService) proxyClass.getConstructor(InvocationHandler.class).newInstance(h);
		proxyService.sayHello();

从代理类$ProxyClass可以看出,我们需要一个类型为InvocationHandler的入参,同时执行proxyService.sayHello()方法时,对应代理类执行的也是InvocationHandler方法逻辑。

  public final void sayHello() {
    try {
      this.h.invoke(this, m3, null);
      return;
    } catch (Error|RuntimeException error) {
      throw null;
    } catch (Throwable throwable) {
      throw new UndeclaredThrowableException(throwable);
    } 
  }

对应我们的实现类

public class InvocationHandlerImpl implements InvocationHandler {
	
	private IPersonService service;
	
	public InvocationHandlerImpl(IPersonService service) {
		this.service = service;
	}

	@Override
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		System.out.println("==>");
		System.out.println("====>");
		Object invoke = method.invoke(service, args);
		System.out.println("======>");
		System.out.println("========>");
		return invoke;
	}
}

以上即是JDK动态代理思想,核心为字节码重组

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值