- 在使用jdk动态代理的时候,必需要实现InvocationHandler接口;invoke方法中该三个参数分别表示为: 代理对象、被代理执行的方法、参数
public class JdkInvocationHandler implements InvocationHandler { /** * 被代理类对象 目标代理对象 */ private Object target; public JdkInvocationHandler(Object target) { this.target = target; } public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println(">>>jdk打印订单日志开始:proxy:"+proxy.getClass().toString()); Object reuslt = method.invoke(target, args);// java的反射机制执行方法 执行目标对象的方法 System.out.println(">>>jdk打印订单日志结束"); return reuslt; } /** * 使用jdk动态代理建立代理类 * * @param <T> * @return */ public <T> T getProxy() { return (T) Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this); } }2.使用jdk动态代理获取代理类对象(JDK自动生成代理类) $Proxy0.class,使用反编译工具java
- 建立代理类$Proxy0源代码文件实现被代理的接口
public final class $Proxy0 extends java.lang.reflect.Proxy implements com.xuyu.service.OrderService {2.使用JavaCompiler技术编译该$Proxy0文件获取到$Proxy0.class数据库
3. 使用ClassLoader将该$Proxy0.class加入到当前JVM内存中设计模式
ClassLoader 顾名思义就是类加载器,ClassLoader 做用:负责将 Class 加载到 JVM 中,审查每一个类由谁加载(父优先的等级加载机制),将 Class字节码 从新解析成 JVM 统一要求的对象格式
1.自定义MyExtJdkInvocationHandler接口 ——至关于InvocationHandler安全
/** * @title: MyExtJdkInvocationHandler */ public interface MyExtJdkInvocationHandler { /** * @param proxy 代理类 * @param method 目标方法 * @param args 参数 * @return * @throws Throwable */ public Object invoke(Object proxy, Method method, Object[] args) throws Throwable; }2.写一个MyJdkInvocationHandler实现MyJdkInvocationHandler接口app
/** * @title: MyJdkInvocationHandler */ public class MyJdkInvocationHandler implements MyExtJdkInvocationHandler { /** * 目标对象 被代理的类 真实访问的类的对象 */ private Object target; public MyJdkInvocationHandler(Object target) { this.target = target; } public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("<<<<<<<<<纯手写jdk动态代理日志开始>>>>>>>>>>"); Object result = method.invoke(target, args);// 使用java的反射执行 System.out.println("<<<<<<<<纯手写jdk动态代理结束>>>>>>>>>>"); return result; } }service层ide
public interface OrderService { public void order() throws Throwable; }/** * @title: OrderServiceImpl */ public class OrderServiceImpl implements OrderService { public void order() { System.out.println("数据库订单执行操做"); } }3.对比反编译$Proxy0.class来写$Proxy0函数
4.简单测试工具
public class Test001 { public static void main(String[] args) throws Throwable { OrderService orderService = new $Proxy0(new MyJdkInvocationHandler(new OrderServiceImpl())); orderService.order(); } }5.控制台输出结果测试
<<<<<<<<<纯手写jdk动态代理日志开始>>>>>>>>>> 数据库订单执行操做 <<<<<<<<纯手写jdk动态代理结束>>>>>>>>>>
1.先看源码Proxy怎么实现的this
public class Proxy implements java.io.Serializable { .... private static final WeakCache<ClassLoader, Class<?>[], Class<?>> proxyClassCache = new WeakCache<>(new KeyFactory(), new ProxyClassFactory()); .... private static Class<?> getProxyClass0(ClassLoader loader, Class<?>... interfaces) { if (interfaces.length > 65535) { throw new IllegalArgumentException("interface limit exceeded"); } //【2】获取代理类,写入到到本地文件中.. return proxyClassCache.get(loader, interfaces); } .... private static final class ProxyClassFactory implements BiFunction<ClassLoader, Class<?>[], Class<?>> { private static final String proxyClassNamePrefix = "$Proxy"; private static final AtomicLong nextUniqueNumber = new AtomicLong(); //【3】将源代码编译成class文件,帮助咱们初始化,建立class文件 @Override public Class<?> apply(ClassLoader loader, Class<?>[] interfaces) { Map<Class<?>, Boolean> interfaceSet = new IdentityHashMap<>(interfaces.length); for (Class<?> intf : interfaces) { Class<?> interfaceClass = null; try { interfaceClass = Class.forName(intf.getName(), false, loader); } catch (ClassNotFoundException e) { } if (interfaceClass != intf) { throw new IllegalArgumentException( intf + " is not visible from class loader"); } if (!interfaceClass.isInterface()) { throw new IllegalArgumentException( interfaceClass.getName() + " is not an interface"); } if (interfaceSet.put(interfaceClass, Boolean.TRUE) != null) { throw new IllegalArgumentException( "repeated interface: " + interfaceClass.getName()); } } //####代理的包名,可自定义#### String proxyPkg = null; int accessFlags = Modifier.PUBLIC | Modifier.FINAL; for (Class<?> intf : interfaces) { 。。。。 } if (proxyPkg == null) { proxyPkg = ReflectUtil.PROXY_PACKAGE + "."; } //####原子类,自增,保证线程安全,原子类计数代理类proxy0,proxy1,proxy2....#### long num = nextUniqueNumber.getAndIncrement(); String proxyName = proxyPkg + proxyClassNamePrefix + num; //####建立Java源代码,转化为字节码文件#### byte[] proxyClassFile = ProxyGenerator.generateProxyClass( proxyName, interfaces, accessFlags); try { //【4】使用classLoader 加载到内存中,代理类class文件加载到内存#### return defineClass0(loader, proxyName, proxyClassFile, 0, proxyClassFile.length); } catch (ClassFormatError e) { throw new IllegalArgumentException(e.toString()); } } } .... @CallerSensitive public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) throws IllegalArgumentException { 。。。。 //【1】建立代理类java源码文件,写入到硬盘中.. Class<?> cl = getProxyClass0(loader, intfs); 。。。。1.总结相关要点
1.建立代理类java源码文件,写入到硬盘中.. 2. 写入到到本地文件中.. 3. 将源代码编译成class文件 4.使用classLoader 加载到内存中..2.模仿源码写代码
/** * @title: MyProxy */ public class MyProxy { static String rt = "\r\t"; public static Object newProxyInstance(JavaClassLoader javaClassLoader, Class<?> classInfo, MyExtJdkInvocationHandler h) { //1.拼接代理类的源代码 try { // 1.建立代理类java源码文件,写入到硬盘中.. Method[] methods = classInfo.getMethods(); String proxyClass = "package com.xuyu.ext.proxy;" + rt + "import java.lang.reflect.Method;" + rt + "import com.xuyu.ext.proxy.MyExtJdkInvocationHandler;" + rt + "public class $Proxy0 implements " + classInfo.getName() + "{" + rt + "MyExtJdkInvocationHandler h;" + rt + "public $Proxy0(MyExtJdkInvocationHandler h)" + "{" + rt + "this.h= h;" + rt + "}" + getMethodString(methods, classInfo) + rt + "}"; // 2. 写入到到本地文件中.. String filename = "d:/code/$Proxy0.java"; File f = new File(filename); FileWriter fw = new FileWriter(f); fw.write(proxyClass); fw.flush(); fw.close(); // 3. 将源代码编译成class文件 JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); StandardJavaFileManager fileMgr = compiler.getStandardFileManager(null, null, null); Iterable units = fileMgr.getJavaFileObjects(filename); JavaCompiler.CompilationTask t = compiler.getTask(null, fileMgr, null, null, null, units); t.call(); fileMgr.close(); // 4.使用classLoader 加载到内存中.. Class<?> $Proxy0 = javaClassLoader.findClass("$Proxy0"); // 5.指明初始化有参数构造函数 Constructor<?> constructor = $Proxy0.getConstructor(MyExtJdkInvocationHandler.class); Object o = constructor.newInstance(h); return o; } catch (Exception e) { e.printStackTrace(); } return null; } public static String getMethodString(Method[] methods, Class intf) { String proxyMe = ""; for (Method method : methods) { proxyMe += "public void " + method.getName() + "() throws Throwable {" + rt + "Method md= " + intf.getName() + ".class.getMethod(\"" + method.getName() + "\",new Class[]{});" + rt + "this.h.invoke(this,md,null);" + rt + "}" + rt; } return proxyMe; } public static void main(String[] args) { newProxyInstance(null, OrderService.class, null); } }3.看源码怎么实现ClassLoader类加载器
4.写出本身的JavaClassLoader 类加载器
public class JavaClassLoader extends ClassLoader { private File classPathFile; public JavaClassLoader(){ String classPath="D:\\code"; this.classPathFile=new File(classPath); } @Override public Class<?> findClass(String name) throws ClassNotFoundException { String className= JavaClassLoader.class.getPackage().getName()+"."+name; if(classPathFile!=null){ File classFile=new File(classPathFile,name.replaceAll("\\.","/")+".class"); if(classFile.exists()){ FileInputStream in=null; ByteArrayOutputStream out=null; try { in=new FileInputStream(classFile); out=new ByteArrayOutputStream(); byte[] buff=new byte[1024]; int len; while ((len=in.read(buff))!=-1){ out.write(buff,0,len); } return defineClass(className,out.toByteArray(),0,out.size()); }catch (Exception e){ e.printStackTrace(); }finally { if(in!=null){ try { in.close(); } catch (IOException e) { e.printStackTrace(); } } if(out!=null){ try { out.close(); } catch (IOException e) { e.printStackTrace(); } } } } } return null; }5.测试类
/** * @title: Test001 */ public class Test001 { public static void main(String[] args) throws Throwable { OrderService orderService = (OrderService) MyProxy.newProxyInstance(new JavaClassLoader(), OrderService.class, new MyJdkInvocationHandler(new OrderServiceImpl())); orderService.order(); } }
6.运行程序生成的$Proxy0.java文件内容
package com.xuyu; import com.xuyu.ext.proxy.MyExtJdkInvocationHandler; import java.lang.reflect.Method; public class $Proxy0 implements com.xuyu.service.OrderService { MyExtJdkInvocationHandler h; public $Proxy0(MyExtJdkInvocationHandler h) { this.h = h; } public void order() throws Throwable { Method md = com.xuyu.service.OrderService.class.getMethod("order", new Class[] { }); this.h.invoke(this, md, null); } }7.控制台输出结果
<<<<<<<<<纯手写jdk动态代理日志开始>>>>>>>>>> 数据库订单执行操做 <<<<<<<<纯手写jdk动态代理结束>>>>>>>>>>
版权@须臾之余https://my.oschina.net/u/3995125
本文参考:
蚂蚁课堂:www.mayikt.com