1.2 动态代理-自己实现一个

//代码生成、编译、重新动态loader到JVM中
public class YustClassLoader  extends ClassLoader{
    private File baseDir;
    public YustClassLoader() {
        String baseDir = YustClassLoader.class.getResource("").getPath();
        this.baseDir = new File(baseDir)  ;
    }
    @Override
    protected Class<?> findClass(String name) throws ClassNotFoundException {
        String className = YustClassLoader.class.getPackage().getName();
        if(Objects.nonNull(baseDir)){
            File classFile = new File(baseDir, name.replaceAll("\\.", "/") + ".class");
            if (classFile.exists()){
                try(FileInputStream in =new FileInputStream(classFile); ByteArrayOutputStream 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 (FileNotFoundException e) {
                    e.printStackTrace();
                } catch (IOException e) {
                    e.printStackTrace();
                }finally {
                    classFile.delete();
                }
            }
        }
        return null;
    }
}
public interface YustInvocationHandler {
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable;
}
public class YustMeipo implements YustInvocationHandler {
    private Person target;//被代理对象的引用作为一个成员变量进行保存下来了
    public Object getInstance(Person target)throws  Exception{
        this.target=target;
        Class clazz = target.getClass();
        System.out.println("被代理对象的class是:"+clazz);
        return YustProxy.newProxyInstance(new YustClassLoader(), clazz.getInterfaces(), this);
    }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("我是媒婆:你的性别是:"+this.target.getSex()+"得给你找个异性");
        System.out.println("-----------------------------");
        method.invoke(this.target, args);
        System.out.println("-----------------------------");
        return null;
    }
}
public class YustProxy {
    private static String ln = "\r\n";
    public static Object newProxyInstance(YustClassLoader classLoader,Class<?>[] interfaces,YustInvocationHandler h){
        try{
            //1、生成源代码
            String proxySrc = generateSrc(interfaces[0]);
            //2、将生成的源代码输出到磁盘,保存为.java文件
            String filePath = YustProxy.class.getResource("").getPath();
            File f = new File(filePath + "$Proxy0.java");
            FileWriter fw = new FileWriter(f);
            fw.write(proxySrc);
            fw.flush();
            fw.close();
            //3、编译源代码,并且生成.class文件
            JavaCompiler  compiler = ToolProvider.getSystemJavaCompiler();
            StandardJavaFileManager manager = compiler.getStandardFileManager(null, null, null);
            Iterable iterable = manager.getJavaFileObjects(f);
            CompilationTask task = compiler.getTask(null, manager, null, null, null, iterable);
            task.call();
            manager.close();
            //4.将class文件中的内容,动态加载到JVM中来
            Class proxyClass = classLoader.findClass("$Proxy0");
            Constructor c = proxyClass.getConstructor(YustInvocationHandler.class);
            f.delete();
            //5.返回被代理后的代理对象
            return c.newInstance(h);

        }catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
    private static String generateSrc(Class<?> interfaces){
        StringBuffer src = new StringBuffer();
        src.append("package com.yust5273.proxy.custom;" + ln);
        src.append("import java.lang.reflect.Method;" + ln);
        src.append("import com.yust5273.proxy.custom.YustInvocationHandler" + ln);
        src.append("public class $Proxy0 implements " + interfaces.getName() + "{" + ln);
        src.append("YustInvocationHandler h;" + ln);
        src.append("public $Proxy0(YustInvocationHandler h) {" + ln);
        src.append("this.h = h;" + ln);
        src.append("}" + ln);
        for (Method m : interfaces.getMethods()) {
            src.append("public " + m.getReturnType().getName() + " " + m.getName() + "(){" + ln);
            src.append("try{" + ln);
            src.append("Method m = " + interfaces.getName() + ".class.getMethod(\"" +m.getName()+"\",new Class[]{});" + ln);
            src.append("this.h.invoke(this,m,null);" + ln);
            src.append("}catch(Throwable e){e.printStackTrace();}" + ln);
            src.append("}" + ln);
        }
        src.append("}");
        return src.toString();
    }
}
public class YustTestFindLove {
    public static void main(String[] args){
        try {
            Person obj =(Person) new YustMeipo().getInstance(new XiaoXingXing());
            System.out.println(obj.getClass());
            obj.findLove();
            //代理对象的实现原理
            //1.拿到被代理对象的引用,然后获取它的接口、
            //2.JDK代理 就会重新生成一个类同时实现我们给的代理对象的所实现的接口
            //3.把被代理对象的引用也拿到了
            //4.重新生成一个class字节码
            //5.然后编译
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

转载于:https://www.jianshu.com/p/d8eafba961db

猜你喜欢

转载自blog.csdn.net/weixin_34080951/article/details/91318841
1.2