RE|GoF23种设计模式-动态代理

栏目: 后端 · 发布时间: 5年前

内容简介:代理(Proxy)是一种设计模式,提供了对目标对象另外的访问方式;即通过代理对象访问目标对象.这样做的好处是:可以在目标对象实现的基础上,增强额外的功能操作,即扩展目标对象的功能。符合开闭原则。代理模式属于结构型 模式,有静态代理和动态代理。需求:现在我们需要根据类型来分别把数据上传到不同Ftp服务。动态代理有以下特点:

代理(Proxy)是一种设计模式,提供了对目标对象另外的访问方式;即通过代理对象访问目标对象.这样做的好处是:可以在目标对象实现的基础上,增强额外的功能操作,即扩展目标对象的功能。符合开闭原则。代理模式属于结构型 模式,有静态代理和动态代理。

静态代理

需求:现在我们需要根据类型来分别把数据上传到不同Ftp服务。

/**
 * 数据的模型类
 */
public static class Data {

    private Integer type;
    private String name;
    private String sex;

    public Integer getType() {
        return type;
    }

    public void setType(Integer type) {
        this.type = type;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

}


public static interface IFTPService {
    void upload(Data data);
}

public static class FTPService implements IFTPService {

    @Override
    public void upload(Data data) {
        System.out.println("Data{" +
                "type=" + data.getType() +
                ", name='" + data.getName() + '\'' +
                ", sex='" + data.getSex() + '\'' +
                '}');
    }

}

public static class FTPServiceStaticProxy implements IFTPService {

    private IFTPService ftpService;

    // 静态代理 构造注入的方式赋值
    public FTPServiceStaticProxy(IFTPService ftpService) {
        this.ftpService = ftpService;
    }

    @Override
    public void upload(Data data) {
        before();
        if (data.getType() % 2 == 0) {
            System.out.println("上传到服务器 1");
            ftpService.upload(data);
        } else {
            System.out.println("上传到服务器 2");
            ftpService.upload(data);
        }
        after();
    }

    private void before(){
        System.out.println("Proxy before method.");
    }
    private void after(){
        System.out.println("Proxy after method.");
    }
}


public static void main(String[] args) {
    Data data = new Data();
    data.setName("Name Zhuang San");
    data.setSex("男");
    data.setType(1);
    new FTPServiceStaticProxy(new FTPService()).upload(data);

    Data data2 = new Data();
    data.setName("Name Wan Wu");
    data.setSex("男");
    data.setType(2);
    new FTPServiceStaticProxy(new FTPService()).upload(data);
}

复制代码

动态代理

动态代理有以下特点:

  1. 代理对象,不需要实现接口
  2. 代理对象的生成,是利用JDK的API,动态的在内存中构建代理对象(需要我们指定创建代理对象/目标对象实现的接口的类型)
  3. 动态代理也叫做: JDK代理,接口代理

JDK 实现方式

/**
 * 数据的模型类
 */
public static class Data {

    private Integer type;
    private String name;
    private String sex;

    public Integer getType() {
        return type;
    }

    public void setType(Integer type) {
        this.type = type;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

}

public static interface IFTPService {
    void upload(Data data);
}

public static class FTPService implements IFTPService {

    @Override
    public void upload(Data data) {
        System.out.println("Data{" +
                "type=" + data.getType() +
                ", name='" + data.getName() + '\'' +
                ", sex='" + data.getSex() + '\'' +
                '}');
    }

}

public static class JDKProxyFTPService implements InvocationHandler {

    private Object target;

    public Object upload(Object target) {
        this.target = target;
        Class<?> clazz = target.getClass();
        // 如何实现的代理?
        return Proxy.newProxyInstance(clazz.getClassLoader(), clazz.getInterfaces(), this);
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        // 只让 upload 方法进入
        if (!"upload".equals(method.getName())) return method.invoke(target, args);
        before(args[0]);
        Object r = method.invoke(target, args);
        after();
        return r;
    }

    private void before(Object data){
        System.out.println("Proxy before method.");
        if (data instanceof Data) { // 判断是否属于 -- Data 模型
            Data d = (Data) data;
            if (d.getType() % 2 == 0)
                System.out.println("上传到服务器 1");
            else
                System.out.println("上传到服务器 2");
        }
    }
    private void after(){
        System.out.println("Proxy after method.");
    }


}

public static void main(String[] args) {
    IFTPService ftpService = (IFTPService) new JDKProxyFTPService().upload(new FTPService());
    Data data = new Data();
    data.setName("Name Zhuang San");
    data.setSex("男");
    data.setType(1);
    ftpService.upload(data);
}

复制代码

Proxy 是如何实现的呢?

我们都知道 JDK Proxy 采用字节重组,重新生的对象来替代原始的对象以达到动态代理的目的。JDK Proxy 生成对象的步骤如下:

  1. 拿到被代理对象的引用,并且获取到它的所有的接口,反射获取。
  2. JDK Proxy 类重新生成一个新的类、同时新的类要实现被代理类所有实现的所有的接口。
  3. 动态生成 Java 代码,把新加的业务逻辑方法由一定的逻辑代码去调用(在代码中体现)。
  4. 编译新生成的 Java 代码.class。
  5. 再重新加载到 JVM 中运行。
public static void main(String[] args) throws IOException {
    //通过反编译 工具 可以查看源代码
    byte [] bytes = ProxyGenerator.generateProxyClass("$Proxy0", new Class[]{IFTPService.class});
    FileOutputStream os = new FileOutputStream("E://$Proxy0.class");
    os.write(bytes);
    os.close();
}

复制代码

使用反编译工具,得到java代码如下:

package com.reape.design.pattern.proxy;

import java.lang.reflect.*;
import com.reape.design.pattern.proxy.*;

// 继承了Proxy类  接口我们的 JDKIFTPService
public final class $Proxy0 extends Proxy implements JDKIFTPService
{
    private static Method m1;
    private static Method m3;
    private static Method m2;
    private static Method m0;

    public $Proxy0(final InvocationHandler invocationHandler) {
        super(invocationHandler);
    }

    // 重写了 toString  hashCode equals 指向了原来的地址
    public final boolean equals(final Object o) {
        try {
            return (boolean)super.h.invoke(this, $Proxy0.m1, new Object[] { o });
        }
        catch (Error | RuntimeException error) {
            throw new Error();
        }
        catch (Throwable t) {
            throw new UndeclaredThrowableException(t);
        }
    }

    public final void upload(final JDKData jdkData) {
        try {
            super.h.invoke(this, $Proxy0.m3, new Object[] { jdkData });
        }
        catch (Error | RuntimeException error) {
            throw new Error();
        }
        catch (Throwable t) {
            throw new UndeclaredThrowableException(t);
        }
    }

    public final String toString() {
        try {
            return (String)super.h.invoke(this, $Proxy0.m2, null);
        }
        catch (Error | RuntimeException error) {
            throw new Error();
        }
        catch (Throwable t) {
            throw new UndeclaredThrowableException(t);
        }
    }

    public final int hashCode() {
        try {
            return (int)super.h.invoke(this, $Proxy0.m0, null);
        }
        catch (Error | RuntimeException error) {
            throw new Error();
        }
        catch (Throwable t) {
            throw new UndeclaredThrowableException(t);
        }
    }

    static {
        try {
            $Proxy0.m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object"));
            $Proxy0.m3 = Class.forName("com.reape.design.pattern.proxy.JDKIFTPService").getMethod("upload", Class.forName("com.reape.design.pattern.proxy.JDKData"));
            $Proxy0.m2 = Class.forName("java.lang.Object").getMethod("toString", (Class<?>[])new Class[0]);
            $Proxy0.m0 = Class.forName("java.lang.Object").getMethod("hashCode", (Class<?>[])new Class[0]);
        }
        catch (NoSuchMethodException ex) {
            throw new NoSuchMethodError(ex.getMessage());
        }
        catch (ClassNotFoundException ex2) {
            throw new NoClassDefFoundError(ex2.getMessage());
        }
    }
}

复制代码

手写动态代理

// 1. ClassLoader 自定义

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(){
        String classPath = MyClassLoader.class.getResource("").getPath();
        this.classPathFile = new File(classPath);
    }
    protected 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;
    }
}

// 2. 动态代理实现的接口类
import java.lang.reflect.Method;

/**
 * 动态代理实现的接口类
 */
public interface MyInvocationHandler {

    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable;

}


3. 生成java文件编译为class写入jvm,动态代理

/**
 * 用来生成源代码的工具类
 */
public class MyProxy {


    private static final String ln = "\r\n";
    private static final String t = "\t";

    public static Object newProxyInstance(MyClassLoader classLoader,
                                           Class<?> [] interfaces,
                                   MyInvocationHandler h){
        try {
            // 1.动态生成源代码文件
            String src = generateSrc(interfaces);

            //2、Java 文件输出磁盘
            String filePath = MyProxy.class.getResource("").getPath();
            System.out.println(filePath);
            File f = new File(filePath + "$Proxy0.java");
            FileWriter fw = null;
            fw = new FileWriter(f);
            fw.write(src);
            fw.flush();
            fw.close();
            //3、把生成的.java 文件编译成.class 文件
            JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
            StandardJavaFileManager manage = compiler.getStandardFileManager(null,null,null);
            Iterable iterable = manage.getJavaFileObjects(f);
            JavaCompiler.CompilationTask task =
                    compiler.getTask(null,manage,null,null,null, iterable);
            task.call();
            manage.close();
            //4、编译生成的.class 文件加载到 JVM 中来
            Class<Object> proxyClass = (Class<Object>) classLoader.findClass("$Proxy0");
            Constructor<Object> c = proxyClass.getConstructor(MyInvocationHandler.class);
//            f.delete();
            //5、返回字节码重组以后的新的代理对象
            return c.newInstance(h);
        } catch (IOException | InstantiationException | IllegalAccessException | InvocationTargetException | NoSuchMethodException | ClassNotFoundException e) {
            e.printStackTrace();
        }
        return null;
    }

    private static String generateSrc(Class<?>[] interfaces){
        // interfaces ---> 需要实现的接口的类
        StringBuilder sb = new StringBuilder();
        sb.append("package com.reape.design.pattern.proxy.handwriting;" + ln);
        sb.append("import java.lang.reflect.*;" + ln);
        sb.append("public class $Proxy0 implements").append(interfacesToString(interfaces));
        sb.append(" {").append(ln);
        sb.append(t + "private com.reape.design.pattern.proxy.handwriting.MyInvocationHandler h;" + ln);
        sb.append(t + "public $Proxy0(com.reape.design.pattern.proxy.handwriting.MyInvocationHandler h) { " + ln);
        sb.append(t + t + "this.h = h;" + ln);
        sb.append(t + "}" + ln);
        for (Class<?> anInterface : interfaces) {
            for (Method m : anInterface.getMethods()) {
                Class<?>[] params = m.getParameterTypes();
                Class<?> result = m.getReturnType();
                sb.append(t + "public final ")
                        .append(resultToString(result))
                        .append(" ")
                        .append(m.getName())
                        .append("(")
                        .append(paramsToString(params))
                        .append(") {").append(ln);
                sb.append(t + t + "try {" + ln);
                sb.append(t + t + t)
                        .append(returnToString(result))
                        .append("h.invoke(this, " + "Class.forName(\"")
//                        .append(anInterface.getName())
                        .append("com.reape.design.pattern.proxy.JDKFTPService")
                        .append("\")")
                        .append(".getMethod(").append("\"").append(m.getName()).append("\"").append(", ")
                        .append(paramsFormNameToString(params))
                        .append(")").append(", new Object[]{ p0 });").append(ln);
                sb.append(t + t + "}" + ln);
                sb.append(t + t + "catch(Error | RuntimeException error) { error.printStackTrace();" + ln);
                sb.append(t + t + t + "throw new Error();" + ln);
                sb.append(t + t + "}" + ln);
                sb.append(t + t + "catch (Throwable t) {" + ln);
                sb.append(t + t + t + "throw new UndeclaredThrowableException(t);" + ln);
                sb.append(t + t + "}" + ln);
                sb.append(t + "}" + ln);
            }
        }
        sb.append("}" + ln);
        return sb.toString();
    }

    /**
     * 接口类数组转 String
     * @param interfaces 接口类数组
     * @return 字符串
     */
    private static String interfacesToString(Class<?>[] interfaces) {
        if (interfaces.length < 1) return "";
        StringBuilder sb = new StringBuilder();
        for (Class<?> anInterface : interfaces) {
            sb.append(" ").append(anInterface.getName()).append(",");
        }
        return sb.substring(0, sb.length() - 1);
    }


    private static String paramsToString(Class<?>[] params) {
        if (params.length < 1) return "";
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < params.length; i++) {
            sb.append(params[i].getName()).append(" ").append("p").append(i).append(", ");
        }
        return sb.substring(0, sb.length() - 2);
    }

    private static String paramsFormNameToString(Class<?>[] params) {
        if (params.length < 1) return "";
        StringBuilder sb = new StringBuilder();
        for (Class<?> param : params) {
            sb.append("Class.forName(\"").append(param.getName()).append("\"), ");
        }
        return sb.substring(0, sb.length() - 2);
    }


    private static String resultToString(Class<?> result) {
        String name = result.getName();
        return "void".equals(name) ? "void" : name;
    }

    private static String returnToString(Class<?> result) {
        String name = result.getName();
        return "void".equals(name) ? "" : "return (" + name + ") ";
    }

}

// 4.测试



public class Test implements MyInvocationHandler {

    private Object target;

    public Object get(Object target) {
        this.target = target;
        Class<?> clazz = target.getClass();
        return MyProxy.newProxyInstance(new MyClassLoader(), clazz.getInterfaces(), this);
    }

    private void before(Object data){
        System.out.println(data);
        System.out.println("Proxy before method.");
    }
    private void after(){
        System.out.println("Proxy after method.");
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        // 只让 upload 方法进入
        if (!"upload".equals(method.getName())) return method.invoke(target, args);
        before(args[0]);
        Object r = method.invoke(target, args);
        after();
        return r;
    }


    public static void main(String[] args) {
        JDKIFTPService ftpService = (JDKIFTPService) new Test().get(new JDKFTPService());
        JDKData data = new JDKData();
        data.setName("Name Zhuang San");
        data.setSex("男");
        data.setType(1);
        ftpService.upload(data);
    }

}

// 上面的代码写考虑的不是很完整
// 有很多判断的地方没有判断以及重写 toString ,equals 等

// java的代理是编译为class文件然后写入的到jvm节约的了内存消耗,但是跟cglib对比还是差很远
// cglib是字节码操作

复制代码

CGLib实现

// 导入jar包
// 1. asm.jar
// 2. cglib.jar


public class JDKData {
    private Integer type;
    private String name;
    private String sex;

    public Integer getType() {
        return type;
    }

    public void setType(Integer type) {
        this.type = type;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }
}


public class JDKFTPService implements JDKIFTPService {

    @Override
    public void upload(JDKData data) {
        System.out.println("Data{" +
                "type=" + data.getType() +
                ", name='" + data.getName() + '\'' +
                ", sex='" + data.getSex() + '\'' +
                '}');
    }
}




public class CglibJDK implements MethodInterceptor {

    public Object getInstance(Class<?> clazz) throws Exception{
        Enhancer enhancer = new Enhancer();
        //要把哪个设置为即将生成的新类父类
        enhancer.setSuperclass(clazz);
        enhancer.setCallback(this);
        return enhancer.create();
    }

    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        //业务的增强
        before(objects[0]);
        Object obj = methodProxy.invokeSuper(o,objects);
        after();
        return obj;
    }


    private void before(Object data){
        System.out.println("Proxy before method.");
        System.out.println(data);
        if (data instanceof JDKData) { // 判断是否属于 -- Data 模型
            JDKData d = (JDKData) data;
            if (d.getType() % 2 == 0)
                System.out.println("上传到服务器 1");
            else
                System.out.println("上传到服务器 2");
        }
    }
    private void after(){
        System.out.println("Proxy after method.");
    }
}


// 测试
public static void main(String[] args) {
    try {
        JDKFTPService obj = (JDKFTPService) new CglibJDK().getInstance(JDKFTPService.class);
        JDKData data = new JDKData();
        data.setName("Name Zhuang San");
        data.setSex("男");
        data.setType(1);
        obj.upload(data);
    } catch (Exception e) {
        e.printStackTrace();
    }
}

// 编译得到class文件

package com.reape.design.pattern.proxy.cglib;

import net.sf.cglib.reflect.*;
import net.sf.cglib.core.*;
import net.sf.cglib.proxy.*;
import java.lang.reflect.*;

public class JDKFTPService$$EnhancerByCGLIB$$5a7831ef$$FastClassByCGLIB$$5a694231 extends FastClass
{
    public JDKFTPService$$EnhancerByCGLIB$$5a7831ef$$FastClassByCGLIB$$5a694231(final Class clazz) {
        super(clazz);
    }
    
    public int getIndex(final Signature signature) {
        final String string = signature.toString();
        switch (string.hashCode()) {
            case -2055565910: {
                if (string.equals("CGLIB$SET_THREAD_CALLBACKS([Lnet/sf/cglib/proxy/Callback;)V")) {
                    return 12;
                }
                break;
            }
            case -1882565338: {
                if (string.equals("CGLIB$equals$1(Ljava/lang/Object;)Z")) {
                    return 15;
                }
                break;
            }
            case -1457535688: {
                if (string.equals("CGLIB$STATICHOOK1()V")) {
                    return 19;
                }
                break;
            }
            case -1411842725: {
                if (string.equals("CGLIB$hashCode$3()I")) {
                    return 18;
                }
                break;
            }
            case -894172689: {
                if (string.equals("newInstance(Lnet/sf/cglib/proxy/Callback;)Ljava/lang/Object;")) {
                    return 6;
                }
                break;
            }
            case -623122092: {
                if (string.equals("CGLIB$findMethodProxy(Lnet/sf/cglib/core/Signature;)Lnet/sf/cglib/proxy/MethodProxy;")) {
                    return 20;
                }
                break;
            }
            case -508378822: {
                if (string.equals("clone()Ljava/lang/Object;")) {
                    return 3;
                }
                break;
            }
            case -419626537: {
                if (string.equals("setCallbacks([Lnet/sf/cglib/proxy/Callback;)V")) {
                    return 11;
                }
                break;
            }
            case 560567118: {
                if (string.equals("setCallback(ILnet/sf/cglib/proxy/Callback;)V")) {
                    return 7;
                }
                break;
            }
            case 773140094: {
                if (string.equals("CGLIB$upload$0(Lcom/reape/design/pattern/proxy/cglib/JDKData;)V")) {
                    return 14;
                }
                break;
            }
            case 811063227: {
                if (string.equals("newInstance([Ljava/lang/Class;[Ljava/lang/Object;[Lnet/sf/cglib/proxy/Callback;)Ljava/lang/Object;")) {
                    return 5;
                }
                break;
            }
            case 840180909: {
                if (string.equals("upload(Lcom/reape/design/pattern/proxy/cglib/JDKData;)V")) {
                    return 8;
                }
                break;
            }
            case 973717575: {
                if (string.equals("getCallbacks()[Lnet/sf/cglib/proxy/Callback;")) {
                    return 10;
                }
                break;
            }
            case 1221173700: {
                if (string.equals("newInstance([Lnet/sf/cglib/proxy/Callback;)Ljava/lang/Object;")) {
                    return 4;
                }
                break;
            }
            case 1230699260: {
                if (string.equals("getCallback(I)Lnet/sf/cglib/proxy/Callback;")) {
                    return 9;
                }
                break;
            }
            case 1306468936: {
                if (string.equals("CGLIB$toString$2()Ljava/lang/String;")) {
                    return 16;
                }
                break;
            }
            case 1584330438: {
                if (string.equals("CGLIB$SET_STATIC_CALLBACKS([Lnet/sf/cglib/proxy/Callback;)V")) {
                    return 13;
                }
                break;
            }
            case 1800494055: {
                if (string.equals("CGLIB$clone$4()Ljava/lang/Object;")) {
                    return 17;
                }
                break;
            }
            case 1826985398: {
                if (string.equals("equals(Ljava/lang/Object;)Z")) {
                    return 0;
                }
                break;
            }
            case 1913648695: {
                if (string.equals("toString()Ljava/lang/String;")) {
                    return 1;
                }
                break;
            }
            case 1984935277: {
                if (string.equals("hashCode()I")) {
                    return 2;
                }
                break;
            }
        }
        return -1;
    }
    
    public int getIndex(final String s, final Class[] array) {
        Label_1103: {
            switch (s.hashCode()) {
                case -1776922004: {
                    if (!s.equals("toString")) {
                        break;
                    }
                    switch (array.length) {
                        case 0: {
                            return 1;
                        }
                        default: {
                            break Label_1103;
                        }
                    }
                    break;
                }
                case -1295482945: {
                    if (!s.equals("equals")) {
                        break;
                    }
                    switch (array.length) {
                        case 1: {
                            if (array[0].getName().equals("java.lang.Object")) {
                                return 0;
                            }
                            break Label_1103;
                        }
                        default: {
                            break Label_1103;
                        }
                    }
                    break;
                }
                case -1053468136: {
                    if (!s.equals("getCallbacks")) {
                        break;
                    }
                    switch (array.length) {
                        case 0: {
                            return 10;
                        }
                        default: {
                            break Label_1103;
                        }
                    }
                    break;
                }
                case -838595071: {
                    if (!s.equals("upload")) {
                        break;
                    }
                    switch (array.length) {
                        case 1: {
                            if (array[0].getName().equals("com.reape.design.pattern.proxy.cglib.JDKData")) {
                                return 8;
                            }
                            break Label_1103;
                        }
                        default: {
                            break Label_1103;
                        }
                    }
                    break;
                }
                case -124978609: {
                    if (!s.equals("CGLIB$equals$1")) {
                        break;
                    }
                    switch (array.length) {
                        case 1: {
                            if (array[0].getName().equals("java.lang.Object")) {
                                return 15;
                            }
                            break Label_1103;
                        }
                        default: {
                            break Label_1103;
                        }
                    }
                    break;
                }
                case -60403779: {
                    if (!s.equals("CGLIB$SET_STATIC_CALLBACKS")) {
                        break;
                    }
                    switch (array.length) {
                        case 1: {
                            if (array[0].getName().equals("[Lnet.sf.cglib.proxy.Callback;")) {
                                return 13;
                            }
                            break Label_1103;
                        }
                        default: {
                            break Label_1103;
                        }
                    }
                    break;
                }
                case -29025555: {
                    if (!s.equals("CGLIB$hashCode$3")) {
                        break;
                    }
                    switch (array.length) {
                        case 0: {
                            return 18;
                        }
                        default: {
                            break Label_1103;
                        }
                    }
                    break;
                }
                case 85179481: {
                    if (!s.equals("CGLIB$SET_THREAD_CALLBACKS")) {
                        break;
                    }
                    switch (array.length) {
                        case 1: {
                            if (array[0].getName().equals("[Lnet.sf.cglib.proxy.Callback;")) {
                                return 12;
                            }
                            break Label_1103;
                        }
                        default: {
                            break Label_1103;
                        }
                    }
                    break;
                }
                case 94756189: {
                    if (!s.equals("clone")) {
                        break;
                    }
                    switch (array.length) {
                        case 0: {
                            return 3;
                        }
                        default: {
                            break Label_1103;
                        }
                    }
                    break;
                }
                case 147696667: {
                    if (!s.equals("hashCode")) {
                        break;
                    }
                    switch (array.length) {
                        case 0: {
                            return 2;
                        }
                        default: {
                            break Label_1103;
                        }
                    }
                    break;
                }
                case 161998109: {
                    if (!s.equals("CGLIB$STATICHOOK1")) {
                        break;
                    }
                    switch (array.length) {
                        case 0: {
                            return 19;
                        }
                        default: {
                            break Label_1103;
                        }
                    }
                    break;
                }
                case 495524492: {
                    if (!s.equals("setCallbacks")) {
                        break;
                    }
                    switch (array.length) {
                        case 1: {
                            if (array[0].getName().equals("[Lnet.sf.cglib.proxy.Callback;")) {
                                return 11;
                            }
                            break Label_1103;
                        }
                        default: {
                            break Label_1103;
                        }
                    }
                    break;
                }
                case 857604112: {
                    if (!s.equals("CGLIB$upload$0")) {
                        break;
                    }
                    switch (array.length) {
                        case 1: {
                            if (array[0].getName().equals("com.reape.design.pattern.proxy.cglib.JDKData")) {
                                return 14;
                            }
                            break Label_1103;
                        }
                        default: {
                            break Label_1103;
                        }
                    }
                    break;
                }
                case 1154623345: {
                    if (!s.equals("CGLIB$findMethodProxy")) {
                        break;
                    }
                    switch (array.length) {
                        case 1: {
                            if (array[0].getName().equals("net.sf.cglib.core.Signature")) {
                                return 20;
                            }
                            break Label_1103;
                        }
                        default: {
                            break Label_1103;
                        }
                    }
                    break;
                }
                case 1543336189: {
                    if (!s.equals("CGLIB$toString$2")) {
                        break;
                    }
                    switch (array.length) {
                        case 0: {
                            return 16;
                        }
                        default: {
                            break Label_1103;
                        }
                    }
                    break;
                }
                case 1811874389: {
                    if (!s.equals("newInstance")) {
                        break;
                    }
                    switch (array.length) {
                        case 1: {
                            final String name = array[0].getName();
                            switch (name.hashCode()) {
                                case -845341380: {
                                    if (name.equals("net.sf.cglib.proxy.Callback")) {
                                        return 6;
                                    }
                                    break;
                                }
                                case 1730110032: {
                                    if (name.equals("[Lnet.sf.cglib.proxy.Callback;")) {
                                        return 4;
                                    }
                                    break;
                                }
                            }
                            break Label_1103;
                        }
                        case 3: {
                            if (array[0].getName().equals("[Ljava.lang.Class;") && array[1].getName().equals("[Ljava.lang.Object;") && array[2].getName().equals("[Lnet.sf.cglib.proxy.Callback;")) {
                                return 5;
                            }
                            break Label_1103;
                        }
                        default: {
                            break Label_1103;
                        }
                    }
                    break;
                }
                case 1817099975: {
                    if (!s.equals("setCallback")) {
                        break;
                    }
                    switch (array.length) {
                        case 2: {
                            if (array[0].getName().equals("int") && array[1].getName().equals("net.sf.cglib.proxy.Callback")) {
                                return 7;
                            }
                            break Label_1103;
                        }
                        default: {
                            break Label_1103;
                        }
                    }
                    break;
                }
                case 1905679803: {
                    if (!s.equals("getCallback")) {
                        break;
                    }
                    switch (array.length) {
                        case 1: {
                            if (array[0].getName().equals("int")) {
                                return 9;
                            }
                            break Label_1103;
                        }
                        default: {
                            break Label_1103;
                        }
                    }
                    break;
                }
                case 1951977610: {
                    if (!s.equals("CGLIB$clone$4")) {
                        break;
                    }
                    switch (array.length) {
                        case 0: {
                            return 17;
                        }
                        default: {
                            break Label_1103;
                        }
                    }
                    break;
                }
            }
        }
        return -1;
    }
    
    public int getIndex(final Class[] array) {
        switch (array.length) {
            case 0: {
                return 0;
            }
            default: {
                return -1;
            }
        }
    }
    
    public Object invoke(final int n, final Object o, final Object[] array) throws InvocationTargetException {
        final JDKFTPService$$EnhancerByCGLIB$$5a7831ef jdkftpService$$EnhancerByCGLIB$$5a7831ef = (JDKFTPService$$EnhancerByCGLIB$$5a7831ef)o;
        try {
            switch (n) {
                case 0: {
                    return new Boolean(jdkftpService$$EnhancerByCGLIB$$5a7831ef.equals(array[0]));
                }
                case 1: {
                    return jdkftpService$$EnhancerByCGLIB$$5a7831ef.toString();
                }
                case 2: {
                    return new Integer(jdkftpService$$EnhancerByCGLIB$$5a7831ef.hashCode());
                }
                case 3: {
                    return jdkftpService$$EnhancerByCGLIB$$5a7831ef.clone();
                }
                case 4: {
                    return jdkftpService$$EnhancerByCGLIB$$5a7831ef.newInstance((Callback[])array[0]);
                }
                case 5: {
                    return jdkftpService$$EnhancerByCGLIB$$5a7831ef.newInstance((Class[])array[0], (Object[])array[1], (Callback[])array[2]);
                }
                case 6: {
                    return jdkftpService$$EnhancerByCGLIB$$5a7831ef.newInstance((Callback)array[0]);
                }
                case 7: {
                    jdkftpService$$EnhancerByCGLIB$$5a7831ef.setCallback(((Number)array[0]).intValue(), (Callback)array[1]);
                    return null;
                }
                case 8: {
                    jdkftpService$$EnhancerByCGLIB$$5a7831ef.upload((JDKData)array[0]);
                    return null;
                }
                case 9: {
                    return jdkftpService$$EnhancerByCGLIB$$5a7831ef.getCallback(((Number)array[0]).intValue());
                }
                case 10: {
                    return jdkftpService$$EnhancerByCGLIB$$5a7831ef.getCallbacks();
                }
                case 11: {
                    jdkftpService$$EnhancerByCGLIB$$5a7831ef.setCallbacks((Callback[])array[0]);
                    return null;
                }
                case 12: {
                    JDKFTPService$$EnhancerByCGLIB$$5a7831ef.CGLIB$SET_THREAD_CALLBACKS((Callback[])array[0]);
                    return null;
                }
                case 13: {
                    JDKFTPService$$EnhancerByCGLIB$$5a7831ef.CGLIB$SET_STATIC_CALLBACKS((Callback[])array[0]);
                    return null;
                }
                case 14: {
                    jdkftpService$$EnhancerByCGLIB$$5a7831ef.CGLIB$upload$0((JDKData)array[0]);
                    return null;
                }
                case 15: {
                    return new Boolean(jdkftpService$$EnhancerByCGLIB$$5a7831ef.CGLIB$equals$1(array[0]));
                }
                case 16: {
                    return jdkftpService$$EnhancerByCGLIB$$5a7831ef.CGLIB$toString$2();
                }
                case 17: {
                    return jdkftpService$$EnhancerByCGLIB$$5a7831ef.CGLIB$clone$4();
                }
                case 18: {
                    return new Integer(jdkftpService$$EnhancerByCGLIB$$5a7831ef.CGLIB$hashCode$3());
                }
                case 19: {
                    JDKFTPService$$EnhancerByCGLIB$$5a7831ef.CGLIB$STATICHOOK1();
                    return null;
                }
                case 20: {
                    return JDKFTPService$$EnhancerByCGLIB$$5a7831ef.CGLIB$findMethodProxy((Signature)array[0]);
                }
            }
        }
        catch (Throwable t) {
            throw new InvocationTargetException(t);
        }
        throw new IllegalArgumentException("Cannot find matching method/constructor");
    }
    
    public Object newInstance(final int n, final Object[] array) throws InvocationTargetException {
        try {
            switch (n) {
                case 0: {
                    return new JDKFTPService$$EnhancerByCGLIB$$5a7831ef();
                }
            }
        }
        catch (Throwable t) {
            throw new InvocationTargetException(t);
        }
        throw new IllegalArgumentException("Cannot find matching method/constructor");
    }
    
    public int getMaxIndex() {
        return 20;
    }
}

// 里面使用 extends FastClass
// 子类重写父类的方法
// 父类方法不能是final

复制代码

CGLib 和 JDK 动态代理对比

  1. JDK 动态代理是实现了被代理对象的接口,CGLib 是继承了被代理对象。
  2. JDK 和 CGLib 都是在运行期生成字节码,JDK 是直接写 Class 字节码,CGLib 使用 ASM 框架写 Class 字节码,Cglib 代理实现更复杂,生成代理类比 JDK 效率低。
  3. JDK 调用代理方法,是通过反射机制调用,CGLib 是通过 FastClass 机制直接调用方法, CGLib 执行效率更高。

静态代理和动态的本质区别

  1. 静态代理只能通过手动完成代理操作,如果被代理类增加新的方法,代理类需要同步 新增,违背开闭原则。
  2. 动态代理采用在运行时动态生成代码的方式,取消了对被代理类的扩展限制,遵循开 闭原则。
  3. 若动态代理要对目标类的增强逻辑扩展,结合策略模式,只需要新增策略类便可完成, 无需修改代理类的代码。 代理模式的优缺点 使用代理模式具有以下几个优点:
  • 代理模式能将代理对象与真实被调用的目标对象分离。

  • 一定程度上降低了系统的耦合度,扩展性好。

  • 可以起到保护目标对象的作用。

  • 可以对目标对象的功能增强。

当然,代理模式也是有缺点的:

  1. 代理模式会造成系统设计中类的数量增加。
  2. 在客户端和目标对象增加一个代理对象,会造成请求处理速度变慢。
  3. 增加了系统的复杂度。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

村落效应

村落效应

[加] 苏珊·平克(Susan Pinker) / 青涂 / 浙江人民出版社 / 2017-3-1 / CNY 69.90

 面对面的接触是作为社会性动物的人类最古老、深刻的需求。在互联网时代,社交媒体已经成为人际沟通的主体,人际关系的维系越来越被社交媒体上的点赞、转发、评论代替,在冰冷的互动中,我们失去了真实与温度。面对面的人际关系与接触能让人感受到如村落生活般的归属感,它是一个人免疫力、复原力和影响力的真正来源。虽然互联网拥有毋庸置疑的优势,但是如果我们渴望快乐、健康、长寿……没错,还有智慧,我们就需要想方设法腾......一起来看看 《村落效应》 这本书的介绍吧!

html转js在线工具
html转js在线工具

html转js在线工具

正则表达式在线测试
正则表达式在线测试

正则表达式在线测试

RGB CMYK 转换工具
RGB CMYK 转换工具

RGB CMYK 互转工具