Plusieurs façons d'écrire le mode proxy en mode de conception Java (3)

arrière-plan

Le mode proxy appartient au mode structurel, et le mode proxy est également l'un des modes de conception couramment utilisés dans notre développement. Cette fois, je vais vous expliquer les méthodes d'écriture suivantes du mode proxy, dans l'espoir de vous aider à comprendre plus rapidement le mode proxy , y compris la méthode d'écriture d'un proxy dynamique par vous-même.

proxy statique

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();
    }
}

insérez la description de l'image ici

proxy dynamique 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);
        }
    }
}

insérez la description de l'image ici
insérez la description de l'image ici

Adresse du fichier de téléchargement Jad : https://varaneckas.com/jad/

insérez la description de l'image ici

proxy dynamique 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();
    }
}

insérez la description de l'image ici

Imitez le proxy dynamique jdk pour réaliser un proxy dynamique par lui-même

Facile à se familiariser avec l'implémentation sous-jacente

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();
    }
}

insérez la description de l'image ici

Je suppose que tu aimes

Origine blog.csdn.net/qq_40351360/article/details/128432085
conseillé
Classement