jdk动态代理为什么要接口

jdk的动态代理为什么用接口,内部是什么原理呢?看了几篇文章貌似都没讲的清楚明白,因此来解释一下。先通过一个简单例子实现功能:

//接口
public interface SayService {

	void say(String name);
}
//实现类
public class SayServiceImpl implements SayService{

	@Override
	public void say(String name) {
		System.out.println(name);
	}
}

然后再自定义一个增强类, 实现InvocationHandler接口:

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

public class WavingInvocationHandler  implements InvocationHandler{

	private Object target;

	public void setTarget(Object target) {
		this.target = target;
	}

	@Override
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		System.out.println("方法执行之前!");
		Object obj = method.invoke(target, args);
		System.out.println("方法执行之后!");
		return obj;
	}
}

编写测试方法:

import sun.misc.ProxyGenerator;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.reflect.Proxy;

public class Test {

	public static void main(String[] args) {

		//接口
		SayService sayService = new SayServiceImpl();
		//织入类
		WavingInvocationHandler handler = new WavingInvocationHandler();
		handler.setTarget(sayService);
		//代理类--增强的对象
		SayService s = (SayService) Proxy.newProxyInstance(
				sayService.getClass().getClassLoader(),
				sayService.getClass().getInterfaces(), handler);

		s.say("say()");//执行代理对象完成业务
		/**
		 方法执行之前!
		 say()
		 方法执行之后!
		 */

		//将jdk中生成代理类输出到本地.Class文件,之后可以通过反编译软件打开查看
		createProxyClassFile("test12345",sayService.getClass().getInterfaces());

	}

	private static void createProxyClassFile(String name,Class<?> [] interfaces){
		byte[] data = ProxyGenerator.generateProxyClass(name,interfaces);//该方法为jdk中生成代理类的核心方法
		FileOutputStream out =null;
		try {
			out = new FileOutputStream(name+".class");
			System.out.println((new File(name)).getAbsolutePath());
			out.write(data);
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}finally {
			if(null!=out) try {
				out.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
	
}
好奇心强的小伙伴一定看过newProxyInstance方法看过了,里面的getProxyClass方法创建代理类:

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

具体是里面的哪个方法生成的,小伙伴们不用找半天了,慢慢debug后会发现,就是上面提到的

ProxyGenerator.generateProxyClass()

通过该方法生成的代理类如下:通过反编译查看源码,一看便知接口的作用

JDK的动态代理是靠多态和反射来实现的,它生成的代理类需要实现你传入的接口,并通过反射来得到接口的方法对象(下文中的m3),并将此方法对象传参给增强类(上文中的WavingInvocationHandler类)的invoke方法去执行,从而实现了代理功能,故接口是jdk动态代理的核心实现方式,没有它就无法通过反射找到方法,所以这也是必须有接口的原因。不知道大家明白否可怜

public final class test12345 extends Proxy implements SayService {
    //1、该类实现你传入的接口并实现方法 
    // 2、通过构造方法传入你定义的增强类对象 
    // 3、通过反射该接口,得到接口里的Method对象并传参给增强类,然后执行Invoke实现功能
    private static Method m1;
    private static Method m2;
    private static Method m3;
    private static Method m0;

    public test12345(InvocationHandler paramInvocationHandler) {
        super(paramInvocationHandler);//2.此处的super指向Proxy中的构造方法并赋值(下文的h就是此处的增强类对象),
    }

    //略去无关的hashcode和equals方法
    public final void say(String paramString) {
        try {
            this.h.invoke(this, m3, new Object[]{paramString});//3.此处的h就是InvocationHandler对象,invoke就是你增强类里的方法,传入接口的方法和参数并执行你增强类里的invoke方法,即完成了整个操作!
        } catch (Error | RuntimeException localError) {
            throw localError;
        } catch (Throwable localThrowable) {
            throw new UndeclaredThrowableException(localThrowable);
        }
    }

    static {//1.静态代码块给属性赋值,初始化接口中的方法对象(主要是下面的m3)
        try {
            m1 = Class.forName("java.lang.Object").getMethod("equals", new Class[]{Class.forName("java.lang.Object")});
            m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]);
            m3 = Class.forName("com.chenrui.core.jdk.SayService").getMethod("say", new Class[]{Class.forName("java.lang.String")});
            m0 = Class.forName("java.lang.Object").getMethod("hashCode", new Class[0]);
        } catch (NoSuchMethodException localNoSuchMethodException) {
            throw new NoSuchMethodError(localNoSuchMethodException.getMessage());
        } catch (ClassNotFoundException localClassNotFoundException) {
            throw new NoClassDefFoundError(localClassNotFoundException.getMessage());
        }
    }
}




  • 8
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 28
    评论
评论 28
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值