全家福
被代理类准备

ImServiceImpl
package com.xiang.service.impl;import com.xiang.service.ImService;public class ImServiceImpl implements ImService {@Overridepublic void sendSms() {System.out.println("我在发送消息");}}
ImService
package com.xiang.service;public interface ImService {void sendSms();}
思路分析
参考静态代理,sendSms()方法里面的内容需要程序员自己定义,所以封装成接口(MyInvocationHandler),让程序员自己实现,People是目标对象,也需要程序员自己实现,所以此处删掉。
public class ImProxy implements ImService{private ImService imService;StudentsProxy(ImService imService){this.imService = imService;}@Overridepublic void sendSms(){System.out.println("===> 方法增强前");people.tuition();System.out.println("===> 方法增强后");}}
封装后
package com.xiang.proxy;import com.xiang.proxy.handler.MyInvocationHandler;import com.xiang.service.ImService;import java.lang.reflect.Method;/*** 动态代理生成的执行方法,本来是动态生成的,此处为了学习暂时手动自定义*/public class $Proxy0 implements ImService {private MyInvocationHandler h;public $Proxy0(MyInvocationHandler h){this.h = h;}@Overridepublic void sendSms() {try {Method sendSms = ImService.class.getMethod("sendSms", new Class[]{});h.invoke(h, sendSms, null);} catch (Throwable throwable) {throwable.printStackTrace();}}}
提出的公共接口
MyInvocationHandler
public interface MyInvocationHandler {/*** 要实现的方法* @param proxy 代理类* @param method 被代理类* @param args 被代理类的入参。* @return* @throws Throwable*/Object invoke(Object proxy, Method method, Object[] args)throws Throwable;}
动态代理类
ImProxy
public class ImProxy implements MyInvocationHandler {public Object objFactory;public ImProxy(Object objFactory){this.objFactory = objFactory;}@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println("===> 方法增强前");Object invoke = method.invoke(objFactory, args);System.out.println("===> 方法增强后");return invoke;}}
结论
原理思路
- 使用java语言组装$Proxy0.java源代码 获取实现的接口,使用java的反射技术获取该接口下面的所有方法。
- 将 $Proxy0.java 编异成 $Proxy0.class文件(JavaCompiler 类似于我们在命令行输入的javac)
- 通过classLoader加载到内存中。
MyProxy
package com.xiang.proxy;import com.xiang.proxy.handler.MyInvocationHandler;import com.xiang.proxy.handler.impl.ImProxy;import com.xiang.service.ImService;import com.xiang.service.impl.ImServiceImpl;import javax.tools.JavaCompiler;import javax.tools.JavaFileObject;import javax.tools.StandardJavaFileManager;import javax.tools.ToolProvider;import java.io.File;import java.io.FileWriter;import java.io.IOException;import java.lang.reflect.Constructor;import java.lang.reflect.Method;public class MyProxy{private final static String PATH = "d:/code/"; //保存文件路径private final static String CLASS_NAME = "$Proxy1"; //类名public static Object newProxyInstance(MyClassLoader loader,Class<?> interfaces,MyInvocationHandler h){//1. 获取要生成的代码String对象String proxyClass = getProxyClass(interfaces);//2.写入本地文件String filename = PATH+CLASS_NAME+".java";//文件写入地址whiteFile(proxyClass,filename);//3. 将 $Proxy0.java 编异成 $Proxy0.class文件(JavaCompiler 类似于我们在命令行输入的javac)compiler(filename);//3. 通过classLoader加载到内存中。try {Class<?> clazz = loader.findClass(CLASS_NAME);//构造函数入参对象。Constructor<?> constructor = clazz.getConstructor(MyInvocationHandler.class);return constructor.newInstance(h);} catch (Exception e) {e.printStackTrace();return null;}}/*** 获取拼接代理对象* @return*/public static String getProxyClass(Class<?> interfaces){Method[] methods = interfaces.getMethods();StringBuilder stringBuilder = new StringBuilder();stringBuilder.append("package com.xiang.proxy;");stringBuilder.append("import com.xiang.proxy.handler.MyInvocationHandler;");stringBuilder.append("import java.lang.reflect.Method;");stringBuilder.append("public class "+CLASS_NAME+" implements "+interfaces.getName()+" {\n" );stringBuilder.append(" private MyInvocationHandler h;\n" );stringBuilder.append(" public "+CLASS_NAME+"(MyInvocationHandler h){\n" );stringBuilder.append(" this.h = h;\n" );stringBuilder.append(" }\n" );stringBuilder.append(mothods(methods,interfaces));stringBuilder.append("}");return stringBuilder.toString();}/*** 拼接方法* @param methods* @param interfaces* @return*/public static String mothods(Method[] methods,Class<?> interfaces){StringBuilder stringBuilder = new StringBuilder();for (Method method : methods) {stringBuilder.append("@Override\n");//此处偷懒,都没有返回值stringBuilder.append("public void "+method.getName()+"() {\n" );stringBuilder.append("try {\n" );stringBuilder.append(" Method mothodName = "+interfaces.getName()+".class.getMethod(\""+method.getName()+"\", new Class[]{});\n" );stringBuilder.append(" h.invoke(h, mothodName, null);\n" );stringBuilder.append(" } catch (Throwable throwable) {\n" );stringBuilder.append(" throwable.printStackTrace();\n" );stringBuilder.append(" }\n" );stringBuilder.append("}" );stringBuilder.append(" " );}return stringBuilder.toString();}/*** 文件写入本地*/public static void whiteFile(String fileStirng,String filename){File file = new File(filename);try {FileWriter fw = new FileWriter(file);fw.write(fileStirng);fw.flush();fw.close();} catch (IOException e) {e.printStackTrace();}}public static void compiler(String filename){JavaCompiler javaCompiler = ToolProvider.getSystemJavaCompiler();StandardJavaFileManager fileManager = javaCompiler.getStandardFileManager(null, null, null);Iterable<? extends JavaFileObject> iterable = fileManager.getJavaFileObjects(filename);JavaCompiler.CompilationTask task = javaCompiler.getTask(null, fileManager, null, null, null, iterable);task.call();try {fileManager.close();} catch (IOException e) {e.printStackTrace();}}}
package com.xiang.proxy;import java.io.ByteArrayOutputStream;import java.io.File;import java.io.FileInputStream;import java.io.IOException;public class MyClassLoader extends ClassLoader{private File classPathFile;public MyClassLoader(){this.classPathFile = new File("D:\\code");}@Overridepublic Class<?> findClass(String name) throws ClassNotFoundException {String className = MyClassLoader.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(null != in){try {in.close();} catch (IOException e) {e.printStackTrace();}}if(out != null){try {out.close();} catch (IOException e) {e.printStackTrace();}}}}}return null;}}
代码测试
public static void main(String[] args) {ImService imService = (ImService) newProxyInstance(new MyClassLoader(), ImService.class, new ImProxy(new ImServiceImpl()));imService.sendSms();}
