美文网首页
代理模式

代理模式

作者: 什么都没有说 | 来源:发表于2018-05-31 18:49 被阅读0次

    代理模式的作用:AOP、拦截器、解耦 ...

    1. 静态代理:

    2. 动态代理:

    3. 自己手写动态代理:

    • 结构


      结构图
    • 代理类Proxy
    package xin.zero2one.proxy.myproxy;
    
    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.InputStream;
    import java.lang.reflect.Constructor;
    import java.lang.reflect.Method;
    
    /**
     * Created by jundo on 2018/5/30.
     */
    public class MyProxy {
    
        private final static String ln = "\r\n";
    
        public static Object newProxyInstance(MyClassLoader loader, Class<?>[] interfaces, MyInvocationHandler h){
    
            try {
                //生成$Proxy.java文件,只针对Car对象
                String src = generateSrc(interfaces);
    
                //将$Proxy.java保存到classpath
                String classpath = MyProxy.class.getResource("").getPath();
                File proxyFile = new File(classpath + "$Proxy0.java");
                FileWriter fw = new FileWriter(proxyFile);
                fw.write(src);
                fw.flush();
                fw.close();
    
                //编译$Proxy.java
                JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
                StandardJavaFileManager manager = compiler.getStandardFileManager(null, null, null);
                Iterable<? extends JavaFileObject> iterable = manager.getJavaFileObjects(proxyFile);
                JavaCompiler.CompilationTask task = compiler.getTask(null, manager, null, null, null, iterable);
                task.call();
                manager.close();
    
                //将$Proxy.java加载到内存中
                System.out.println("find class");
                Class<?> proxy0 = loader.findClass("$Proxy0");
                System.out.println("find ok");
                Constructor<?> constructor = proxy0.getConstructor(MyInvocationHandler.class);
                return constructor.newInstance(h);
            }catch (Exception e){
                e.printStackTrace();
            }
            return null;
        }
    
        private static String generateSrc(Class<?>[] interfaces){
            StringBuffer sb = new StringBuffer();
            sb.append("package xin.zero2one.proxy.myproxy;" + ln);
            sb.append("import xin.zero2one.bean.Car;" + ln);
            sb.append("import xin.zero2one.proxy.myproxy.MyInvocationHandler;" + ln);
            sb.append("import java.lang.reflect.Method;" + ln);
            sb.append("public class $Proxy0 implements " + interfaces[0].getName() + "{" + ln);
            sb.append("MyInvocationHandler h;" + ln);
            sb.append("public $Proxy0(MyInvocationHandler h) { " + ln);
            sb.append("this.h = h;");
            sb.append("}" + ln);
            for (Method m : interfaces[0].getMethods()){
                sb.append("public " + m.getReturnType().getName() + " " + m.getName() + "() {" + ln);
                sb.append("try{" + ln);
                sb.append("Method m = " + interfaces[0].getName() + ".class.getMethod(\"" + m.getName() + "\",new Class[]{});" + ln);
                sb.append("this.h.invoke(this,m,null);" + ln);
                sb.append("}catch(Throwable e){" + ln);
                sb.append("e.printStackTrace();" + ln);
                sb.append("}");
                sb.append("}");
            }
            sb.append("}" + ln);
            return sb.toString();
        }
    }
    
    
    • MyInvocationHandler
    package xin.zero2one.proxy.myproxy;
    
    import java.lang.reflect.Method;
    
    /**
     * Created by jundo on 2018/5/30.
     */
    public interface MyInvocationHandler {
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable;
    }
    
    • MyClassLoader
    package xin.zero2one.proxy.myproxy;
    
    import java.io.*;
    
    /**
     * Created by jundo on 2018/5/30.
     */
    public class MyClassLoader extends ClassLoader{
    
        @Override
        protected Class<?> findClass(String name) throws ClassNotFoundException {
            String classpath = MyClassLoader.class.getResource("").getPath();
            String className = MyClassLoader.class.getPackage().getName() + "." + name;
            String filePath = name.replaceAll("\\.", "/");
            File classFile = new File(classpath, filePath + ".class");
            if (classFile.exists()) {
                FileInputStream fis = null;
                ByteArrayOutputStream out = null;
                try {
                    fis = new FileInputStream(classFile);
                    out = new ByteArrayOutputStream();
                    byte[] bytes = new byte[1024];
                    int len;
                    while ((len = fis.read(bytes)) != -1) {
                        out.write(bytes, 0, len);
                    }
                    return defineClass(className, out.toByteArray(), 0, out.size());
                } catch (Exception e) {
                    e.printStackTrace();
                } finally {
                    if (fis != null) {
                        try {
                            fis.close();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                    if (out != null) {
                        try {
                            out.close();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                }
    
            }
            return null;
        }
    }
    
    • 被代理接口Car
    package xin.zero2one.bean;
    
    /**
     * Created by jundo on 2018/5/29.
     */
    public interface Car {
    
        void getCar();
    }
    
    • Car实现类
    package xin.zero2one.bean;
    
    /**
     * Created by jundo on 2018/5/29.
     */
    public class Tesla implements Car{
        @Override
        public void getCar() {
            System.out.println("get tesla");
        }
    }
    
    • Car代理类
    package xin.zero2one.proxy;
    
    import xin.zero2one.bean.Car;
    
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    import java.lang.reflect.Proxy;
    
    /**
     * Created by jundo on 2018/5/29.
     */
    public class CarProxy implements InvocationHandler{
    
        private Car car;
    
        public Object getInstance(Car car){
            this.car = car;
            Class<?> clazz = car.getClass();
            Class<?>[] interfaces = clazz.getInterfaces();
            Car obj = (Car) Proxy.newProxyInstance(clazz.getClassLoader(), interfaces, this);
            return obj;
        }
    
    
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            System.out.println("找车子啦");
            System.out.println(method == null);
            method.invoke(this.car,args);
            System.out.println("就决定是你了");
            return null;
        }
    }
    
    • 测试类
    package xin.zero2one.proxy.myproxy;
    
    import xin.zero2one.bean.Car;
    import xin.zero2one.bean.Tesla;
    
    /**
     * Created by jundo on 2018/5/30.
     */
    public class MyProxyTest {
    
        public static void main(String[] args) {
            MyCarProxy proxy = new MyCarProxy();
            Car car = (Car)proxy.getInstance(new Tesla());
            car.getCar();
        }
    }
    

    相关文章

      网友评论

          本文标题:代理模式

          本文链接:https://www.haomeiwen.com/subject/jigqsftx.html