1.接口IndexDao public interface IndexDao { public void query(); public String queryString(String name,Integer age); }
2.实现类IndexDaoImpl public class IndexDaoImpl implements IndexDao { public void query() { System.out.println(“query”); }
public String queryString(String name, Integer age) { System.out.println("proxy-string"); return ""; }}
3.通用类代码示例ProxyUtil:
public class ProxyUtil {
//获取代理对象---插入的逻辑固定 public static Object createProxy(Object target){ String line = "\n";//换行 String tab = "\t";//缩进 Class targetClazz = target.getClass().getInterfaces()[0];//获取传入对象的接口 String targetClazzName = targetClazz.getName(); String targetClazzSimpleName = targetClazz.getSimpleName(); //接口中的方法 Method[] methods = targetClazz.getDeclaredMethods(); //类中的内容 String content = ""; //包声明 String packageContent = "package com.proxy;"+line; //导入声明 String importContent = "import "+targetClazzName+";"+line; //类定义 String firstLineContent = "public class $Proxy implements "+targetClazzSimpleName+" {"+line; //属性 String filedContent = tab+"private "+targetClazzSimpleName+" target;"+line; //构造方法 String constructorContent = tab+"public $Proxy("+targetClazzSimpleName+" target){" +line+ tab+tab+"this.target = target;" +line+ tab+"}"+line; //方法实现 String methodContent = ""; for (Method method : methods) { String returnType = method.getReturnType().getSimpleName();//返回类型 String methodName = method.getName();//方法名 Class[] params = method.getParameterTypes();//参数类型 int index = 0; String paramContent = ""; String paramNames = ""; //参数列表 if(params != null && params.length > 0){ for (int i=0;i<params.length;i++){ Class param = params[i]; String paramTypeName = param.getSimpleName(); paramContent += paramTypeName+" p"+index+","; paramNames += "p"+index+","; index++; } paramContent = paramContent.substring(0,paramContent.lastIndexOf(",")); paramNames = paramNames.substring(0,paramNames.lastIndexOf(",")); } if(returnType.equals("void")){ methodContent += tab+"public void "+methodName+"("+paramContent+") {"+line+ tab+tab+"System.out.println(\"proxy\");"+line+ tab+tab+"target."+methodName+"("+paramNames+");"+line+ tab+"}"+line; }else { methodContent += tab+"public "+returnType+" "+methodName+"("+paramContent+") {"+line+ tab+tab+"System.out.println(\"proxy-param\");"+line+ tab+tab+"return target."+methodName+"("+paramNames+");"+line+ tab+"}"+line; } } content = packageContent + importContent + firstLineContent + filedContent + constructorContent + methodContent + "}" + line; //将java对象入文件保存到本地 File file =new File("e:\\com\\proxy\\$Proxy.java"); try { if (!file.exists()) { file.createNewFile(); } FileWriter fw = new FileWriter(file); fw.write(content); fw.flush(); fw.close(); //将.java文件编译成.class文件 JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); StandardJavaFileManager fileMgr = compiler.getStandardFileManager(null, null, null); Iterable units = fileMgr.getJavaFileObjects(file); JavaCompiler.CompilationTask t = compiler.getTask(null, fileMgr, null, null, null, units); t.call(); fileMgr.close(); //使用ClassLoader创建对象 URL[] urls = new URL[]{new URL("file:e:\\\\")}; URLClassLoader urlClassLoader = new URLClassLoader(urls); Class clazz = urlClassLoader.loadClass("com.proxy.$Proxy"); //根据构造方法创建对象 Constructor constructor = clazz.getConstructor(targetClazz); return constructor.newInstance(target); //clazz.newInstance(); //Class.forName() }catch (Exception e){ e.printStackTrace(); } return null; }//获取代理对象升级–加入业务
public static Object createProxyNew(Class targetClazz, TestInvocationHandler th){ String line = "\n";//换行 String tab = "\t";//缩进 String targetClazzName = targetClazz.getName(); String targetClazzSimpleName = targetClazz.getSimpleName(); String thSimpleName = th.getClass().getSimpleName(); //接口中的方法 Method[] methods = targetClazz.getDeclaredMethods(); //类中的内容 String content = ""; //包声明 String packageContent = "package com.proxy;"+line; //导入声明 String importContent = "import "+targetClazzName+";"+line+ "import java.lang.reflect.Method;"+line+ "import com.spring.dao.TestInvocationHandler;"+line; //类定义 String firstLineContent = "public class $Proxy implements "+targetClazzSimpleName+" {"+line; //属性 String filedContent = tab+"private TestInvocationHandler target;"+line; //构造方法 String constructorContent = tab+"public $Proxy(TestInvocationHandler target){" +line+ tab+tab+"this.target = target;" +line+ tab+"}"+line; //方法实现 String methodContent = ""; for (Method method : methods) { String returnType = method.getReturnType().getSimpleName();//返回类型 String methodName = method.getName();//方法名 Class[] params = method.getParameterTypes();//参数类型 int index = 0; String paramContent = ""; String paramNames = ""; String paramTypes = ""; String paramArrays = ""; //参数列表 if(params != null && params.length > 0){ paramTypes = ","; for (int i=0;i<params.length;i++){ Class param = params[i]; String paramTypeName = param.getSimpleName(); paramContent += paramTypeName+" p"+index+","; paramNames += "p"+index+","; paramTypes += paramTypeName+".class,"; index++; } paramContent = paramContent.substring(0,paramContent.lastIndexOf(",")); paramNames = paramNames.substring(0,paramNames.lastIndexOf(",")); paramTypes = paramTypes.substring(0,paramTypes.lastIndexOf(",")); } if(returnType.equals("void")){ methodContent += tab+"public void "+methodName+"("+paramContent+") {"+line+ tab+tab+"try{"+line+ tab+tab+tab+"Method method = Class.forName(\""+targetClazzName+"\").getDeclaredMethod(\""+methodName+"\""+paramTypes+");"+line+ tab+tab+tab+"Object[] params = new Object[]{"+paramNames+"};"+line+ tab+tab+tab+"target.invoke(method,params);"+line+ tab+tab+"}catch(Exception e){"+line+ tab+tab+tab+"e.printStackTrace();"+line+ tab+tab+"}"+line+ tab+"}"+line; }else { methodContent += tab+"public "+returnType+" "+methodName+"("+paramContent+") {"+line+ tab+tab+"try{"+line+ tab+tab+tab+"Method method = Class.forName(\""+targetClazzName+"\").getDeclaredMethod(\""+methodName+"\""+paramTypes+");"+line+ tab+tab+tab+"Object[] params = new Object[]{"+paramNames+"};"+line+ tab+tab+tab+"return ("+returnType+")target.invoke(method,params);"+line+ tab+tab+"}catch(Exception e){"+line+ tab+tab+tab+"e.printStackTrace();"+line+ tab+tab+"}"+line+ tab+tab+"return null;"+line+ tab+"}"+line; } } content = packageContent + importContent + firstLineContent + filedContent + constructorContent + methodContent + "}" + line; //将java对象入文件保存到本地 File file =new File("e:\\com\\proxy\\$Proxy.java"); try { if (!file.exists()) { file.createNewFile(); } FileWriter fw = new FileWriter(file); fw.write(content); fw.flush(); fw.close(); //将.java文件编译成.class文件 JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); StandardJavaFileManager fileMgr = compiler.getStandardFileManager(null, null, null); Iterable units = fileMgr.getJavaFileObjects(file); JavaCompiler.CompilationTask t = compiler.getTask(null, fileMgr, null, null, null, units); t.call(); fileMgr.close(); //使用ClassLoader创建对象 URL[] urls = new URL[]{new URL("file:e:\\\\")}; URLClassLoader urlClassLoader = new URLClassLoader(urls); Class clazz = urlClassLoader.loadClass("com.proxy.$Proxy"); //根据构造方法创建对象 Constructor constructor = clazz.getConstructor(TestInvocationHandler.class); return constructor.newInstance(th); //return clazz.newInstance(); //Class.forName() }catch (Exception e){ e.printStackTrace(); } return null; }}
4.模拟JDK代理接口
public interface TestInvocationHandler { public Object invoke(Method method, Object[] args); }
5.模拟JDK代理实现类
public class TestInvocationHandlerImpl implements TestInvocationHandler {
private Object target; public TestInvocationHandlerImpl(Object target){ this.target = target; } @Override public Object invoke(Method method, Object[] args) { try { return method.invoke(target,args); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } return null; }}
6.测试类Test public class Test {
public static void main(String[] args) { //自定义动态代理 IndexDao indexDao = (IndexDao) ProxyUtil.createProxyNew(IndexDao.class, new TestInvocationHandlerImpl(new IndexDaoImpl())); indexDao.query(); indexDao.queryString("ok",1); //jdk动态代理 /*IndexDao proxy = (IndexDao) Proxy.newProxyInstance(Test.class.getClassLoader(), new Class[]{IndexDao.class},new ProxyInvocationHandler(new IndexDaoImpl())); proxy.queryString("jdkProxy",2);*/ }}
这是一个手写的简易动态代理模型,spring底层的动态代理比这个复杂很多,不过对于一个菜鸟,对我理解代理有很大帮助。