No_1 手写Proxy
手写动态代理主要原理:
userDAO=(UserDAO)Proxy.newProxyinstance(classloader,interfaces[],new MyInvocationHandler(targer);
userDAO.save();
public class AppMain { //上课老师的代码 public static void main(String[] args) { UserDAO userDAO = new UserDAO(); Object proxyObject = newProxy(userDAO); IDAO idao = (IDAO) proxyObject; idao.save(); } public static Object newProxy(Object target) { // 生成动态类,类的方法来之接口,得到Class对象 /// class[]数组中放的是UserDAO的所有接口类信息 Class[] interfaces = target.getClass().getInterfaces(); // 需要类加载器 ClassLoader classLoader = target.getClass().getClassLoader(); // 回调myHandler MyInvocationHandler myHandler = new MyInvocationHandler(target); // 调用java动态处理框架 Object proxyObject = Proxy.newProxyInstance(classLoader, interfaces, new MyInvocationHandler(target) { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { // TODO Auto-generated method stub System.out.println("日志"); return super.invoke(target, method, args); } }); return proxyObject; } static class MyInvocationHandler implements InvocationHandler { Object target; public MyInvocationHandler(Object target) { super(); this.target = target; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("日志"); method.invoke(target, args); return null; } } }
1=. class ZProxy { public Object newProxyinstance( classLoader, interfaces, new MyInvocationHandler(target){
1.拼写字符串,public class MyProxy { @1 有一个构造方法 接受handler; @2 调用方法query{ 里面是handler.invoke(this,method,arges)} ,注意这个第一个参数是this对象;
生成的动态代理对象
package com.jv.own; import com.jv.own.UserDao; import java.lang.reflect.Method; import com.jv.own.MyInvocationHandler; public class MyProxy implements UserDao{ private MyInvocationHandler handler; public MyProxy(MyInvocationHandler handler){ this.handler = handler; } public com.jv.own.User query(java.lang.String p1){ try{ Object[] args = new Object[]{p1}; Method method = com.jv.own.UserDao.class.getMethod("query",Class.forName("java.lang.String")); return (com.jv.own.User)handler.invoke(this,method,args); }catch(Throwable e){ return null; } } }
2. 根据生成的MyProxy类,利用构造方法生成对象,同时传入handler对象;return constructors[0].newInstance(handler);
URL[] urls = new URL[]{new URL("file:f\\\\projects\\own\\spring-framework-master\\proxy\\out\\production\\classes")}; URLClassLoader urlClassLoader = new URLClassLoader(urls); Class clazz = urlClassLoader.loadClass("com.jv.own.MyProxy"); //############################################实例化############################################ //返回 Constructor[] constructors = clazz.getConstructors(); constructors[0].newInstance(handler); return constructors[0].newInstance(handler);
3. done
第一个类
package com.jv.own; import java.io.FileWriter; import java.lang.reflect.Constructor; import java.lang.reflect.Method; import java.net.URL; import java.net.URLClassLoader; import javax.tools.JavaCompiler; import javax.tools.StandardJavaFileManager; import javax.tools.ToolProvider; public class MyProxyUtil { private static final String l = "\n\r"; private static final String t = "\t"; public static Object newInstance(ClassLoader classLoader,Class[] interfaces,MyInvocationHandler handler) throws Exception{ StringBuilder sb = new StringBuilder(); StringBuilder sbImport = new StringBuilder(); StringBuilder sbImplements = new StringBuilder(); StringBuilder sbMethods = new StringBuilder(); //############################################生成源代码############################################ //包定义 sb.append("package com.jv.own;").append(l+l); if(interfaces == null || interfaces.length==0){ throw new Exception("接口不能为空"); } //生成导入和implements for (Class anInterface : interfaces) { sbImport.append("import "+anInterface.getName()+";"+l); sbImplements.append(anInterface.getSimpleName()+","); } sbImport.append("import java.lang.reflect.Method;").append(l+l); sbImport.append("import com.jv.own.MyInvocationHandler;").append(l+l); sb.append(sbImport.toString()); String temp = sbImplements.toString().substring(0,sbImplements.toString().lastIndexOf(",")); //类定义 sb.append("public class MyProxy implements ").append(temp).append("{").append(l).append(l); sb.append(t+"private MyInvocationHandler handler;").append(l); //构造函数 sb.append(t+"public MyProxy(").append("MyInvocationHandler handler){").append(l); sb.append(t+t+"this.handler = handler;").append(l).append(t).append("}").append(l).append(l); //生成接口里面所有的 for (Class anInterface : interfaces) { Method[] methods = anInterface.getMethods(); for (Method method : methods) { String parameter = ""; String parameterType = ""; int i = 1; for(Class cl:method.getParameterTypes()){ parameter += cl.getName() + " p" + i++ +","; parameterType += "Class.forName(\""+cl.getTypeName()+"\")"+","; } if(parameter!=null&&!parameter.equals("")) { parameter = parameter.substring(0, parameter.lastIndexOf(",")); parameterType = parameterType.substring(0, parameterType.lastIndexOf(",")); } sbMethods.append(t).append("public ").append(method.getReturnType().getName()).append(" ").append(method.getName()) .append("(").append(parameter).append("){").append(l+t+t); sbMethods.append("try{").append(l+t+t+t); String args = "Object[] args = new Object[]{"; for(int j=1;j<i;j++){ args += "p"+j+","; } args = args.substring(0,args.lastIndexOf(","))+"};"; sbMethods.append(args).append(l+t+t+t); StringBuilder methodContent = new StringBuilder(); //methodContent.append("Method method = Class.forName(\""+anInterface.getTypeName()+"\").getMethod(\""+method.getName()+"\","+parameterType+");"); methodContent.append("Method method = "+anInterface.getName()+".class.getMethod(\""+method.getName()+"\","+parameterType+");"); sbMethods.append(methodContent.toString()).append(l+t+t+t); if(method.getReturnType().getName().equals("void")){ sbMethods.append("handler.invoke(this,method,args);").append(l+t+t); }else{ sbMethods.append("return "+"("+method.getReturnType().getName()+")"+"handler.invoke(this,method,args);").append(l+t+t); } sbMethods.append("}catch(Throwable e){"+l+t+t+t+"return null;"+l+t+t+"}"+l+t); sbMethods.append("}").append(l); } } sb.append(sbMethods.toString()); sb.append("}"); System.out.println(sb.toString()); //############################################将源代码写入磁盘文件############################################ String filePath = MyProxyUtil.class.getResource("").getPath() + "MyProxy.java"; System.out.println(filePath); FileWriter fileWriter = new FileWriter(filePath); fileWriter.write(sb.toString()); fileWriter.flush(); fileWriter.close(); //############################################编译源代码############################################ JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); StandardJavaFileManager fileManager = compiler.getStandardFileManager(null, null, null); Iterable iterable = fileManager.getJavaFileObjects(filePath); JavaCompiler.CompilationTask task = compiler.getTask(null, fileManager, null, null, null, iterable); task.call(); fileManager.close(); //############################################将文件通过URLClassLocader或者自定义ClassLoader进行加载############################################ URL[] urls = new URL[]{new URL("file:f\\\\projects\\own\\spring-framework-master\\proxy\\out\\production\\classes")}; URLClassLoader urlClassLoader = new URLClassLoader(urls); Class clazz = urlClassLoader.loadClass("com.jv.own.MyProxy"); //############################################实例化############################################ //返回 Constructor[] constructors = clazz.getConstructors(); constructors[0].newInstance(handler); return constructors[0].newInstance(handler); } }
第二个handler接口
package com.jv.own; import java.lang.reflect.Method; public interface MyInvocationHandler { public Object invoke(Object proxy, Method method, Object[] args) throws Throwable; }
第三个主app
package com.jv.own; public class TestMyProxy { public static void main(String[] args) { MyInvocationHandler handler = new MyOwnInvocationHandler(new UserDaoImpl()); try { UserDao dao = (UserDao)MyProxyUtil.newInstance(com.jv.own.UserDao.class.getClassLoader(),new Class[]{UserDao.class},handler); dao.query("a"); } catch (Exception e) { e.printStackTrace(); } } }
第四个接口
package com.jv.own; public class User { private String userName; public String getUserName() { return userName; } public void setUserName(String userName) { this.userName = userName; } } ------------------------------ package com.jv.own; public interface UserDao { User query(String name); } -------------------------------- package com.jv.own; public class UserDaoImpl implements UserDao { @Override public User query(String name) { System.out.println("UserDaoImpl execute query"); return null; } }
自己的handler
package com.jv.own; import java.lang.reflect.Method; public class MyOwnInvocationHandler implements MyInvocationHandler{ private UserDao target; public MyOwnInvocationHandler(UserDao target){ this.target = target; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("invoke before"); method.invoke(target,args); System.out.println("invoke after"); return null; } }
托管地址
https://github.com/atzhangsan/common_projects.git
atzhang5月29