1、概念
“动态代理是指代理类对象在程序运行时由JVM根据反射机制动态生成的。动态代理不需要定义代理类的,java源文件。 动态代理其实就是jdk运行期间,动态创建class字节码并加载到JVM。”
2、实例
public interface SmsService { String send(String message); } public class SmsServiceImpl implements SmsService { public SmsServiceImpl() { } public String send(String message) { System.out.println("send success:" + message); return "send success:" + message; } } public class SmsInvocationHandler implements InvocationHandler { final Object target; public SmsInvocationHandler(Object target) { this.target = target; } public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("before invoke:" + method.getName()); Object result = method.invoke(this.target, args); System.out.println("after invoke:" + method.getName()); return result; } } public class JDKProxyFactory { public JDKProxyFactory() { } public static Proxy getProxy(Object target) { return (Proxy)Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), new SmsInvocationHandler(target)); } } public class Test { public static void main(String[] args) { System.setProperty("sun.misc.ProxyGenerator.saveGeneratedFiles", "true"); SmsServiceImpl s = new SmsServiceImpl(); SmsService proxy = (SmsService)JDKProxyFactory.getProxy(s); proxy.send("hello"); System.out.println("$Proxy0.class全名: "+Proxy.getProxyClass(SmsService.class.getClassLoader(), SmsService.class)); } } |
3、问题
1)为什么jdk动态代理,必须实现接口?
是由jdk动态代理底层实现决定的。 生成的代理类$Proxy0 本身继承了Proxy,在java中只能继承一个类,所以只能实现需要代理的类的接口。
通过设置,可以在我们的项目根目录下生成代理类class文件,也就是$Proxy0.class
System.setProperty("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");
但是改代理类会有自己的包目录,通过下面代码查看代理类的包目录。
System.out.println("$Proxy0.class全名: "+Proxy.getProxyClass(SmsService.class.getClassLoader(), SmsService.class));
然后代开改代理类,如下:
package com.sun.proxy; import com.yuanxin.testjar.agent.jdka.SmsService; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import java.lang.reflect.UndeclaredThrowableException; public final class $Proxy0 extends Proxy implements SmsService { private static Method m1; private static Method m2; private static Method m3; private static Method m0; public $Proxy0(InvocationHandler var1) throws { super(var1); } public final String send(String var1) throws { try { return (String)super.h.invoke(this, m3, new Object[]{var1}); } catch (RuntimeException | Error var3) { throw var3; } catch (Throwable var4) { throw new UndeclaredThrowableException(var4); } } static { try { m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object")); m2 = Class.forName("java.lang.Object").getMethod("toString"); m3 = Class.forName("com.yuanxin.testjar.agent.jdka.SmsService").getMethod("send", Class.forName("java.lang.String")); m0 = Class.forName("java.lang.Object").getMethod("hashCode"); } catch (NoSuchMethodException var2) { throw new NoSuchMethodError(var2.getMessage()); } catch (ClassNotFoundException var3) { throw new NoClassDefFoundError(var3.getMessage()); } } } |
参考:jdk动态代理为什么只能为接口生成代理类?_小小少年_的博客-优快云博客_jdk动态代理为什么必须实现接口JDK动态代理为什么只能代理有接口的类_皇家大少つ的博客-优快云博客_为什么jdk动态代理只能代理接口