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




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

文章插图


那我们看下生成的java文件是什么?
package com.wy.study.proxy;import java.lang.reflect.Method;public class $Proxy0 implements com.wy.study.proxy.IUserService{YjInvocationHandler h;public $Proxy0(YjInvocationHandler h) {this.h = h;}public void saveUser() {try{Method m = com.wy.study.proxy.IUserService.class.getMethod("saveUser",new Class[]{});this.h.invoke(this,m,null);}catch(Throwable e){e.printStackTrace();}}}
还有一种,使用javassit也可以实现 Proxy 类.javassit可以自动生成类
前提需要导入javassit jar包:
package com.wy.study.proxy;import java.lang.reflect.InvocationHandler;import java.lang.reflect.InvocationTargetException;import java.lang.reflect.Method;import javassist.CannotCompileException;import javassist.ClassPool;import javassist.CtClass;import javassist.CtConstructor;import javassist.CtField;import javassist.CtMethod;import javassist.CtNewMethod;import javassist.LoaderClassPath;import javassist.NotFoundException;import javassist.bytecode.AccessFlag;public class YjProxy2 { public static Method getMethod(Class cla, String name, Class... types) {try {return cla.getMethod(name, types);} catch (NoSuchMethodException e) {throw new RuntimeException(e);} } public void newProxyInstance(ClassLoader loader, Class proxyTarget,InvocationHandler invocationHandler) throws NotFoundException,CannotCompileException, IllegalAccessException,InstantiationException, NoSuchMethodException,InvocationTargetException {ClassPool pool = new ClassPool();pool.insertClassPath(new LoaderClassPath(proxyTarget.getClassLoader()));CtClass targetClass = pool.get(proxyTarget.getName());CtClass proxyClass = pool.makeClass(proxyTarget.getName() + "$proxy",targetClass);CtField handlerField = new CtField(pool.get(InvocationHandler.class.getName()), "h", proxyClass);proxyClass.addField(handlerField);int methodIndex = 0;for (CtMethod ctMethod : targetClass.getDeclaredMethods()) {if (!AccessFlag.isPublic(ctMethod.getModifiers())) {continue;} else if ((ctMethod.getModifiers() & AccessFlag.NATIVE) != 0) {continue;} else if ((ctMethod.getModifiers() & AccessFlag.STATIC) != 0) {continue;} else if ((ctMethod.getModifiers() & AccessFlag.FINAL) != 0) {continue;}String methodFname = ctMethod.getName() + methodIndex;CtField methodField = new CtField(pool.get(Method.class.getName()),methodFname, proxyClass);String paramTypeSrc = "https://www.goobye.net/new Class[]{";for (int i = 0; i < ctMethod.getParameterTypes().length; i++) {if (i != 0)paramTypeSrc += ",";paramTypeSrc += ctMethod.getParameterTypes()[i].getName()+ ".class";}paramTypeSrc += "}";String d = proxyTarget.getName() + ".class";String initSrc = https://www.goobye.net/getClass().getName()+".getMethod(" + d + ",""+ ctMethod.getName() + ""," + paramTypeSrc + ")";proxyClass.addField(methodField, initSrc);CtMethod copymethod = CtNewMethod.copy(ctMethod, proxyClass, null);String bodySrc = "https://www.goobye.net/{";bodySrc += "Object result=h.invoke($0," + methodFname + ",$args);";if (!copymethod.getReturnType().getName().equals("void")) {bodySrc += "return ($r)result;";}bodySrc += "}";copymethod.setBody(bodySrc);proxyClass.addMethod(copymethod);methodIndex++;}CtConstructor constructor = new CtConstructor(new CtClass[] { pool.get(InvocationHandler.class.getName()) },proxyClass);constructor.setBody("h=$1;");proxyClass.addConstructor(constructor);proxyClass.debugWriteFile("D:\");Class cla = proxyClass.toClass();UserServiceImpl i = (UserServiceImpl) cla.getConstructor(InvocationHandler.class).newInstance(invocationHandler);i.getName("11"); } public static void main(String[] args) throws Exception {new YjProxy2().newProxyInstance(YjProxy2.class.getClassLoader(),UserServiceImpl.class, new InvocationHandler() {UserServiceImpl target = new UserServiceImpl();@Overridepublic Object invoke(Object proxy, Method method,Object[] args) throws Throwable {System.out.println("代理前");Object r = method.invoke(target, args);System.out.println("代理后");return r;}}); }}
写到这你明白动态代理底层是怎样实现了吗?欢迎评论!