Múltiples formas de escribir el modo proxy en el modo de diseño Java (3)

fondo

El modo proxy pertenece al modo estructural, y el modo proxy también es uno de los modos de diseño comúnmente utilizados en nuestro desarrollo. Esta vez, explicaremos las siguientes formas de escribir el modo proxy, con la esperanza de ayudarlo a comprender el modo proxy más rápido. , incluido el método de escribir un proxy dinámico por su cuenta .

proxy estático

package com.example.proxy.staticProxy;

public interface IPerson {
    
    
    String findJob();
}
package com.example.proxy.staticProxy;

public class Customer implements  IPerson{
    
    
    @Override
    public String findJob() {
    
    
        return "工作要求:高薪,双休,福利好,事少,压力小";
    }
}

package com.example.proxy.staticProxy;

public class CustomFather implements IPerson{
    
    
    private IPerson iPerson;

    //客户老爸知道他儿子的要求
    public CustomFather(IPerson iPerson) {
    
    
        this.iPerson = iPerson;
    }

    public static void main(String[] args) {
    
    
        CustomFather bossProxy=new CustomFather(new Customer());
        bossProxy.findJob();
    }

    @Override
    public String findJob() {
    
    
        before();
        System.out.println(iPerson.findJob());
        after();
        return null;
    }

    private void after() {
    
    
        System.out.println("找到了,结束....");

    }

    private void before() {
    
    
        System.out.println("客户老爸开始给儿子物色工作....");
    }
}

package com.example.proxy.staticProxy;

public class StaticProxyTest {
    
    
    public static void main(String[] args) {
    
    
        //静态代理也可以使用,只是代理的对象个数很少,如果有其他人也要找工作并不适配,且客户老爸这个类也要经常进行修改
        CustomFather customFather = new CustomFather(new Customer());
        customFather.findJob();
    }
}

inserte la descripción de la imagen aquí

proxy dinámico jdk

package com.example.proxy.jdkProxy;

public interface IPerson {
    
    
    String findJob();
}

package com.example.proxy.jdkProxy;



public class Customer implements IPerson {
    
    
    @Override
    public String findJob() {
    
    
        return "工作要求:高薪,双休,福利好,事少,压力小";
    }
}

package com.example.proxy.jdkProxy;


import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class JdkProxy implements InvocationHandler {
    
    

    private IPerson iPerson;

    public IPerson getProxy(IPerson iPerson) {
    
    
        this.iPerson = iPerson;
        Class clz = iPerson.getClass();
        return (IPerson) Proxy.newProxyInstance(clz.getClassLoader(), clz.getInterfaces(), this);
    }


    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    
    
        before();
        System.out.println(method.invoke(this.iPerson, args));
        after();
        return null;
    }

    private void after() {
    
    
        System.out.println("找到了,结束....");
    }

    private void before() {
    
    
        System.out.println("客户老爸开始给儿子物色工作....");
    }
}

package com.example.proxy.jdkProxy;


public class JdkProxyTest {
    
    
    public static void main(String[] args) {
    
    
        //动态代理,增加客户需求接口,代理类不需要经常变化,单要比cglib的动态代理性能要差一点
        JdkProxy jdkProxy = new JdkProxy();
        IPerson iPerson = jdkProxy.getProxy(new Customer());
        iPerson.findJob();
        
		//使用jdk的工具生成代理类的字节码文件,然后我们可以安装jad反编译工具,进行反编译
        byte bytes[]=ProxyGenerator.generateProxyClass("$Proxy0",new Class[]{
    
    IPerson.class});
        try {
    
    
            FileOutputStream fileOutputStream=new FileOutputStream(new File("d://$Proxy.class"));
            fileOutputStream.write(bytes);
            fileOutputStream.close();
        } catch (FileNotFoundException e) {
    
    
            throw new RuntimeException(e);
        } catch (IOException e) {
    
    
            throw new RuntimeException(e);
        }
    }
}

inserte la descripción de la imagen aquí
inserte la descripción de la imagen aquí

Dirección del archivo de descarga de Jad: https://varaneckas.com/jad/

inserte la descripción de la imagen aquí

proxy dinámico cglib

package com.example.proxy.cglibProxy;

public class Customer   {
    
    

    public String findJob() {
    
    
        return "工作要求:高薪,双休,福利好,事少,压力小";
    }
}

package com.example.proxy.cglibProxy;

import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;

public class CglibProxy implements MethodInterceptor {
    
    

    public Object getProxy(Class<?> clz) {
    
    
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(clz);
        enhancer.setCallback(this);
        return enhancer.create();
    }

    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
    
    
        before();
        System.out.println(methodProxy.invokeSuper(o,objects));
        after();
        return null;
    }

    private void after() {
    
    
        System.out.println("找到了,结束....");
    }

    private void before() {
    
    
        System.out.println("客户老爸开始给儿子物色工作....");
    }
}

package com.example.proxy.cglibProxy;

public class CglibProxyTest {
    
    
    public static void main(String[] args) {
    
    
        // cglib的动态代理推荐使用,因为性能比jdk都好
        // 注意custom类中不能用final修饰的方法
        CglibProxy cglibProxy = new CglibProxy();
        Customer customer = (Customer) cglibProxy.getProxy(new Customer().getClass());
        customer.findJob();
    }
}

inserte la descripción de la imagen aquí

Imite el proxy dinámico jdk para realizar el proxy dinámico por sí mismo

Fácil de familiarizarse con la implementación subyacente

package com.example.proxy.customProxy;

public interface IMyPerson {
    
    
    String findJob();
}

package com.example.proxy.customProxy;

import java.io.*;

public class MyClassLoader extends ClassLoader {
    
    
    private File classFilePath;

    public MyClassLoader() {
    
    
        this.classFilePath = new File(MyClassLoader.class.getResource("").getPath());
    }

    @Override
    protected Class<?> findClass(String name) throws ClassNotFoundException {
    
    
        String classname = MyClassLoader.class.getPackage().getName() + "." + name;
        if (classFilePath != null) {
    
    
            File file = new File(classFilePath, name.replaceAll("\\.","/") + ".class");
            if (file.exists()) {
    
    
                try {
    
    
                    FileInputStream fis = new FileInputStream(file);
                    ByteArrayOutputStream bos = new ByteArrayOutputStream();
                    byte buff[] = new byte[1024];
                    int len;
                    while ((len = fis.read(buff)) != -1) {
    
    
                        bos.write(buff, 0, len);
                    }
                    return defineClass(classname, bos.toByteArray(), 0, bos.size());
                } catch (Exception e) {
    
    
                    throw new RuntimeException(e);
                }
            }
        }
        return null;
    }
}

package com.example.proxy.customProxy;


import com.example.proxy.jdkProxy.IPerson;

public class MyCustomer implements IMyPerson {
    
    
    @Override
    public String findJob() {
    
    
        return "工作要求:高薪,双休,福利好,事少,压力小";
    }
}

package com.example.proxy.customProxy;

import java.lang.reflect.Method;

public interface MyInvocationHandler {
    
    
    public Object invoke(Object proxy, Method method, Object[] args)
            throws Throwable;
}

package com.example.proxy.customProxy;

import javax.tools.JavaCompiler;
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.InvocationHandler;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

public class MyProxy {
    
    

    public static Object newProxyInstance(MyClassLoader loader,
                                          Class<?>[] interfaces,
                                          MyInvocationHandler h)
            throws IllegalArgumentException {
    
    
        //Step1 生成代理类的java文件
        String originCode = generate(interfaces);
        //System.out.println(originCode);
        //Step2 把生成代理类的java文件写到磁盘$Proxy0.java
        String path = MyProxy.class.getResource("").getPath();
        File file = new File(path + "$Proxy0.java");
        try {
    
    
            FileWriter fileWriter = new FileWriter(file);
            fileWriter.write(originCode);
            fileWriter.flush();
            fileWriter.close();

            //Step3 将java文件编译成class文件$Proxy0.class
            JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
            StandardJavaFileManager manager = compiler.getStandardFileManager(null, null, null);
            Iterable iterable = manager.getJavaFileObjects(file);

            JavaCompiler.CompilationTask compilationTask = compiler.getTask(null, manager, null, null, null, iterable);
            compilationTask.call();
            manager.close();


            //Step4 将class文件加载到jvm中
            Class clz = loader.findClass("$Proxy0");
            Constructor constructor = clz.getConstructor(MyInvocationHandler.class);


            //Step5 将生成java文件删除
            file.delete();

            return constructor.newInstance(h);

        } catch (Exception e) {
    
    
            e.printStackTrace();
        }
        return null;
    }

    private static String generate(Class<?>[] interfaces) {
    
    
        String ln = "\r\n";
        StringBuffer sb = new StringBuffer();
        sb.append("package com.example.proxy.customProxy;" + ln);
        sb.append("import java.lang.reflect.*;" + ln);
        sb.append("import com.example.proxy.customProxy.IMyPerson;" + ln);

        sb.append("public class $Proxy0 implements " + interfaces[0].getName() + " {" + ln);
        sb.append("private MyInvocationHandler h;" + ln);

        sb.append("    public $Proxy0(MyInvocationHandler invocationhandler)\n" +
                "    {
    
    \n" + ln +
                "        this.h=invocationhandler;\n" + ln +
                "    }" + ln);
//方法由于我们只有一个,就写死了是一个,如果多个,可以用循环
        sb.append("public final String findJob()\n" + ln +
                "    {
    
    \n" + ln +
                "        try\n" + ln +
                "        {
    
    \n" + ln +
                "           Method m = com.example.proxy.customProxy.IMyPerson.class.getMethod(\"findJob\",new Class[]{});"+ ln +
                "            return (String)this.h.invoke(this, m, new Object[]{});\n" + ln +
                "        }\n" + ln +
                "        catch(Error _ex) { " + ln +
                "throw new UndeclaredThrowableException(_ex);" + ln +
                "}\n" + ln +
                "        catch(Throwable throwable)\n" + ln +
                "        {
    
    \n" +
                "            throw new UndeclaredThrowableException(throwable);\n" + ln +
                "        }\n" + ln +
                "    }" + ln);







        sb.append("}" + ln);


        return sb.toString();
    }

    private static String toLowerFirstCase(String src){
    
    
        char [] chars = src.toCharArray();
        chars[0] += 32;
        return String.valueOf(chars);
    }
    private static Map<Class,Class> mappings = new HashMap<Class, Class>();
    static {
    
    
        mappings.put(int.class,Integer.class);
    }

    private static String getReturnEmptyCode(Class<?> returnClass){
    
    
        if(mappings.containsKey(returnClass)){
    
    
            return "return 0;";
        }else if(returnClass == void.class){
    
    
            return "";
        }else {
    
    
            return "return null;";
        }
    }

    private static String getCaseCode(String code,Class<?> returnClass){
    
    
        if(mappings.containsKey(returnClass)){
    
    
            return "((" + mappings.get(returnClass).getName() +  ")" + code + ")." + returnClass.getSimpleName() + "Value()";
        }
        return code;
    }

    private static boolean hasReturnValue(Class<?> clazz){
    
    
        return clazz != void.class;
    }

}

package com.example.proxy.customProxy;

import java.lang.reflect.Method;

public class MyProxyProxy implements MyInvocationHandler{
    
    

    private IMyPerson iMyPerson;

    public IMyPerson getProxy(IMyPerson iMyPerson) {
    
    
        this.iMyPerson = iMyPerson;
        Class<?> clz=iMyPerson.getClass();
        return (IMyPerson) MyProxy.newProxyInstance(new MyClassLoader(),clz.getInterfaces(),this);
    }


    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    
    
        before();
        System.out.println(method.invoke(this.iMyPerson, args));
        after();
        return null;
    }

    private void after() {
    
    
        System.out.println("找到了,结束....");
    }

    private void before() {
    
    
        System.out.println("客户老爸开始给儿子物色工作....");
    }

}

package com.example.proxy.customProxy;



public class MyProxyProxyTest {
    
    


    public static void main(String[] args) {
    
    
        //动态代理,增加客户需求接口,代理类不需要经常变化,单要比cglib的动态代理性能要差一点
        MyProxyProxy myProxyProxy = new MyProxyProxy();
        IMyPerson iPerson = myProxyProxy.getProxy(new MyCustomer());
        iPerson.findJob();
    }
}

inserte la descripción de la imagen aquí

Supongo que te gusta

Origin blog.csdn.net/qq_40351360/article/details/128432085
Recomendado
Clasificación