jdk动态代理为什么只能实现接口-jdk动态代理为什么必须有接口


原因如下:
1、生成的代理类继承了Proxy,由于java是单继承,所以只能实现接口,通过接口实现
2、从代理模式的设计来说,充分利用了java的多态特性,也符合基于接口编码的规范
下面我们从底层的实现来看动态代理的原理:
目录:
1、什么是动态代理
2、动态代理的写法
3、手写动态代理
什么是动态代理?为其他对象提供一种代理以控制对这个对象的访问 。
Java 对动态代理提供了内建的支持,在java.lang.reflect包下面,提供了一个Proxy 的类和一个InvocationHandler的接口 。
通常把使用Java内建的对代理模式支持的功能来实现的代理称为Java的动态代理 。动态代理和静态代理相比,明显的变化是:静态代理 实现的时候,在Subject接口上定义很多的方法,代理类里面自然要实现很多方法;而动态代理实现的时候,虽然Subject接口上 定义了很多方法,但是动态代理类始终只要一个invoke方法 。这样,当Subject接口发生变化的时候,动态代理的接口就不需要跟着变化了 。
Java 动态代理目标只能代理接口,基本的实现是依靠Java的反射机制和动态生成class的技术,来动态生产被代理的接口的实现对象 。如果对类实行代理,则可以使用cglib;


动态代理的写法我们 来实现保存用户的功能,使用事务代理来管理事务;
(1) 代理类的实现
要实现接口InvocationHandler接口 。需要提供一个方法来实现:把具体的目标对象 和动态代理绑定起来,并在绑定好过后,返回被代理的目标对象的接口,以利于客户端的操作 。
需要实现invoke方法,在这个方法里面,具体判断当前在调用什么方法,需要如何处理 。
具体代码如下:
public class TransactionProxy implements InvocationHandler{private Object target;public TransactionProxy( Object target){this.target = target;}@Overridepublic Object invoke( Object proxy, Method method, Object[] args ) throws Throwable {try {System.out.println("開始事務.................");method.invoke(this.target,args);}catch (Exception e){System.out.println("回滾事務..............");}finally {System.out.println("提交事務..............");}return null;}}
其他类如下:
public interface IUserService{void saveUser();}public class UserServiceImpl implements IUserService {@Overridepublic void saveUser() {System.out.println("save user ....");}}
测试类:
public class TestProxy{public static void main( String[] args ) {UserServiceImpl userService = new UserServiceImpl();IUserService proxyUserService = (IUserService) Proxy.newProxyInstance(userService.getClass().getClassLoader(),userService.getClass().getInterfaces(),new TransactionProxy(userService));proxyUserService.saveUser();}}


jdk动态代理为什么只能实现接口-jdk动态代理为什么必须有接口

文章插图


我们看一下生成的代理类:


jdk动态代理为什么只能实现接口-jdk动态代理为什么必须有接口

文章插图


我们看下生成的类:
public final class proy0 extends Proxy implements UserServiceImpl {private static Method m1;private static Method m8;private static Method m3;private static Method m2;private static Method m6;private static Method m5;private static Method m7;private static Method m9;private static Method m0;private static Method m4;public proy0(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 void notify() throws{try {super.h.invoke(this, m8, (Object[])null);} catch (RuntimeException | Error var2) {throw var2;} catch (Throwable var3) {throw new UndeclaredThrowableException(var3);}}public final void saveUser() 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);}}public final void wait(long var1) throws InterruptedException {try {super.h.invoke(this, m6, new Object[]{Long.valueOf(var1)});} catch (RuntimeException | InterruptedException | Error var4) {throw var4;} catch (Throwable var5) {throw new UndeclaredThrowableException(var5);}}public final void wait(long var1, int var3) throws InterruptedException {try {super.h.invoke(this, m5, new Object[]{Long.valueOf(var1), Integer.valueOf(var3)});} catch (RuntimeException | InterruptedException | Error var5) {throw var5;} catch (Throwable var6) {throw new UndeclaredThrowableException(var6);}}public final Class getClass() throws{try {return (Class)super.h.invoke(this, m7, (Object[])null);} catch (RuntimeException | Error var2) {throw var2;} catch (Throwable var3) {throw new UndeclaredThrowableException(var3);}}public final void notifyAll() throws{try {super.h.invoke(this, m9, (Object[])null);} catch (RuntimeException | Error var2) {throw var2;} catch (Throwable var3) {throw new UndeclaredThrowableException(var3);}}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 wait() throws InterruptedException {try {super.h.invoke(this, m4, (Object[])null);} catch (RuntimeException | InterruptedException | 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")});m8 = Class.forName("com.wy.study.proxy.UserServiceImpl").getMethod("notify", new Class[0]);m3 = Class.forName("com.wy.study.proxy.UserServiceImpl").getMethod("saveUser", new Class[0]);m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]);m6 = Class.forName("com.wy.study.proxy.UserServiceImpl").getMethod("wait", new Class[]{Long.TYPE});m5 = Class.forName("com.wy.study.proxy.UserServiceImpl").getMethod("wait", new Class[]{Long.TYPE, Integer.TYPE});m7 = Class.forName("com.wy.study.proxy.UserServiceImpl").getMethod("getClass", new Class[0]);m9 = Class.forName("com.wy.study.proxy.UserServiceImpl").getMethod("notifyAll", new Class[0]);m0 = Class.forName("java.lang.Object").getMethod("hashCode", new Class[0]);m4 = Class.forName("com.wy.study.proxy.UserServiceImpl").getMethod("wait", new Class[0]);} catch (NoSuchMethodException var2) {throw new NoSuchMethodError(var2.getMessage());} catch (ClassNotFoundException var3) {throw new NoClassDefFoundError(var3.getMessage());}}}