• 5.代理设计模式


    彻底搞懂代理模式实现原理
    什么是代理模式
    代理模式主要对我们方法执行之前与之后实现增强
    代理模式应用场景

    1.日志的采集
    2.权限控制
    3.实现aop
    4.Mybatis mapper
    5.Spring的事务
    6.全局捕获异常
    7.Rpc远程调用接口
    8.代理数据源
    9.自定义注解+反射+aop技术

    核心思想:解决代码的冗余性的问题

    代理模式实现的原理

    抽象主题角色:可以是接口,也可以是抽象类;
    委托类角色:真实主题角色,业务逻辑的具体执行者;
    代理类角色:内部含有对真实对象ServiceImpl的引用,负责对真实主题角色的调用,并在真实主题角色处理前后做预处理和后处理。

    代理模式创建方式

    静态代理
    静态代理需要自己人工编写代理类代码
    基于接口实现方式

    public class OrderServiceProxy  implements  OrderService{
        private OrderService orderService;
    
        public OrderServiceProxy(OrderService orderService) {
            this.orderService = orderService;
        }
    
        public String addOrder(String userName, String userPwd) {
            System.out.println("使用静态代理类打印日志开始:userName:" + userName + "," + userPwd);
            String result = orderService.addOrder(userName, userPwd);
            System.out.println("使用静态代理类打印日志结束:userName:" + userName + "," + userPwd);
            return result;
        }
    }
    
    
    
    public interface OrderService {
        /**
         * 需要被代理的方法
         * @return
         */
         String addOrder(String userName,String userPwd);
    }
    
    
    public class Test001 {
        public static void main(String[] args) {
            OrderService orderService = new OrderServiceProxy(new OrderServiceImpl());
            orderService.addOrder("mayikt","123456");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32

    基于继承的实现方式

    public class OrderServiceProxy  extends OrderServiceImpl {
        private OrderService orderService;
    
        public OrderServiceProxy(OrderService orderService) {
            this.orderService = orderService;
        }
    
        public String addOrder(String userName, String userPwd) {
            System.out.println("使用静态代理类打印日志开始:userName:" + userName + "," + userPwd);
            String result = super.addOrder(userName, userPwd);
            System.out.println("使用静态代理类打印日志结束:userName:" + userName + "," + userPwd);
            return result;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    动态代理与静态代理的区别

    动态代理不需要写代理类对象,通过程序自动生成,而静态代理需要我们自己写代理类对象。
    Jdk生成字节码技术
    ASM

    动态代理
    动态代理是在实现阶段不用关心代理类,而在运行阶段才指定哪一个对象。
    动态代理类的源码是在程序运行期间由JVM根据反射等机制动态的生成 。

    Jdk动态代理
    JDK动态代理的一般步骤如下:
    1.创建被代理的接口和类;
    2.实现InvocationHandler接口,对目标接口中声明的所有方法进行统一处理;
    3.调用Proxy的静态方法,创建代理类并生成相应的代理对象;

    实现原理:利用拦截器机制必须实现InvocationHandler接口中的invoke方法实现对
    我们的目标方法增强。

    public class JdkInvocationHandler implements InvocationHandler {
        /**
         * 目标对象
         */
        private Object target;
    
        public JdkInvocationHandler(Object target) {
            this.target = target;
        }
    
        /**
         * @param proxy  使用jdk程序生成的代理类
         * @param method 目标方法
         * @param args   方法需要传递的参数
         * @return
         */
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            System.out.println("使用Jdk动态代理打印日志开始" + args[0]);
            Object result = method.invoke(target, args);
            System.out.println("使用Jdk动态代理打印日志结束" + args[1]);
            return result;
        }
    
        /**
         * 生成代理类
         *
         * @param <T>
         * @return
         */
        public <T> T getProxy() {
            return (T) Proxy.newProxyInstance(target.getClass().getClassLoader(),
                    target.getClass().getInterfaces(), this);
        }
    
    }
    
    public class JdkInvocationHandler implements InvocationHandler {
        /**
         * 目标对象
         */
        private Object target;
    
        public JdkInvocationHandler(Object target) {
            this.target = target;
        }
    
        /**
         * @param proxy  使用jdk程序生成的代理类
         * @param method 目标方法
         * @param args 方法需要传递的参数
         * @return
         */
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            System.out.println("使用Jdk动态代理打印日志开始" + args[0]);
            Object result = method.invoke(target, args);
            System.out.println("使用Jdk动态代理打印日志结束" + args[1]);
            return result;
        }
    
        public <T> T getProxy() {
            return (T) Proxy.newProxyInstance(target.getClass().getClassLoader(),
                    target.getClass().getInterfaces(), this);
        }
    
    }
    
    
    JdkInvocationHandler jdkInvocationHandler = new JdkInvocationHandler(new OrderServiceImpl());
    OrderServiceImpl orderService = jdkInvocationHandler.getProxy();
    orderService.addOrder("mayikt", "meite");
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70

    加上该代码:

    1.获取代理的生成的class文件
    System.getProperties().put(“sun.misc.ProxyGenerator.saveGeneratedFiles”, “true”);

    2.使用反编译工具该Proxy0.class

    注意:继承了Proxy类,实现了代理的接口,由于java不能多继承,这里已经继承了Proxy类了,不能再继承其他的类,所以JDK的动态代理不支持对实现类的代理,只支持接口的代理。

    纯手写Jdk动态代理

    思路分析:
    1.定义InvocationHandler类 回调方法
    2.使用java反射技术获取接口下所有的方法,拼接 P r o x y 0. j a v a 代 码 3. 在 将 Proxy0.java代码 3.在将 Proxy0.java3.Proxy0.java编译成class文件,读取到内存中

    public class $Proxy0 implements com.mayikt.service.OrderService {
    
        private MayiktJdkInvocationHandler h;
        private static Method m3;
    
        public $Proxy0(MayiktJdkInvocationHandler mayiktJdkInvocationHandler) {
            this.h = mayiktJdkInvocationHandler;
        }
    
        @Override
        public String addOrder(String ver1, String var2) {
            try {
                return (String) h.invoke(this, m3, new Object[]{ver1, var2});
            } catch (RuntimeException | Error var4) {
                throw var4;
            } catch (Throwable var5) {
                throw new UndeclaredThrowableException(var5);
            }
        }
    
        static {
            try {
                m3 = Class.forName("com.mayikt.service.OrderService").getMethod("addOrder", Class.forName("java.lang.String"), Class.forName("java.lang.String"));
            } catch (NoSuchMethodException var2) {
                throw new NoSuchMethodError(var2.getMessage());
            } catch (ClassNotFoundException var3) {
                throw new NoClassDefFoundError(var3.getMessage());
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    public class MyJdkInvocationHandler implements MayiktJdkInvocationHandler {
        /**
         * 目标对象
         */
        private Object target;
    
        public MyJdkInvocationHandler(Object target) {
            this.target = target;
        }
    
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            System.out.println("使用Jdk动态代理打印日志开始" + args[0]);
            Object result = method.invoke(target, args);
            System.out.println("使用Jdk动态代理打印日志结束" + args[1]);
            return result;
        }
        public <T> T getProxy() {
            return (T) new $Proxy0(this);
        }
    }
    
    MyJdkInvocationHandler myJdkInvocationHandler = new MyJdkInvocationHandler(new OrderServiceImpl());
    OrderService orderService = myJdkInvocationHandler.getProxy();
    orderService.addOrder("mayikt", "meite");
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    public class MyProxy {
        private static String rt = "\r\t";
    
        public static Object newProxyInstance(JavaClassLoader classLoader, Class classInfo, MayiktInvocationHandler mayiktInvocationHandler) {
            try {
                // 1.拼接java代理代理源代码
                Method[] methods = classInfo.getMethods();
                String proxyClass = "package com.mayikt.service;" + rt
                        + "import java.lang.reflect.Method;" + rt
                        + "import com.mayikt.service.proxy.MayiktInvocationHandler;" + rt
                        + "import java.lang.reflect.UndeclaredThrowableException;" + rt
                        + "public class $Proxy0 implements " + classInfo.getName() + "{" + rt
                        + "MayiktInvocationHandler h;" + rt
                        + "public $Proxy0(MayiktInvocationHandler h)" + "{" + rt
                        + "this.h= h;" + rt + "}"
                        + getMethodString(methods, classInfo) + rt + "}";
                // 2.将该源代码写入到本地文件中
                String filename = "d:/code/$Proxy0.java";
                File f = new File(filename);
                FileWriter fw = new FileWriter(f);
                fw.write(proxyClass);
                fw.flush();
                fw.close();
                // 3.编译为class文件
                JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
                StandardJavaFileManager fileMgr = compiler.getStandardFileManager(null, null, null);
                Iterable units = fileMgr.getJavaFileObjects(filename);
                JavaCompiler.CompilationTask t = compiler.getTask(null, fileMgr, null, null, null, units);
                t.call();
                fileMgr.close();
                // 4.将class文件加入到内存中
                Class proxy0Class = classLoader.findClass("$Proxy0");
                //5.使用java反射机制给函数中赋值
                Constructor m = proxy0Class.getConstructor(MayiktInvocationHandler.class);
                Object object = m.newInstance(mayiktInvocationHandler);
                return object;
            } catch (Exception e) {
                return null;
            }
        }
    
        public static String getMethodString(Method[] methods, Class intf) {
            String proxyMe = "";
    
            for (Method method : methods) {
                Class<?>[] parameterTypes = method.getParameterTypes();
                StringBuilder sb = new StringBuilder();
                for (int i = 0; i < parameterTypes.length; i++) {
                    sb.append(parameterTypes[i].getName() + " ver" + (i + 1));
                    if (i < parameterTypes.length - 1) {
                        sb.append(" ,");
                    }
                }
                String parameterStr = sb.toString();
                proxyMe = "public " + method.getReturnType().getName() + " " + method.getName() + " ( " + parameterStr + " ) { " +
                        "try {   Method m3 = Class.forName(\"com.mayikt.service.OrderService\").getMethod(\"addOrder\", Class.forName(\"java.lang.String\"), Class.forName(\"java.lang.String\"));" +
                        "return (String) h.invoke(this, m3, new Object[]{ver1, ver2}); } catch (RuntimeException | Error var4) {  throw var4;  } catch (Throwable var5) {   throw new UndeclaredThrowableException(var5); } " +
                        "" +
                        " } ";
    
            }
            return proxyMe;
        }
    
        public static void main(String[] args) {
            newProxyInstance(null, OrderService.class, null);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    public class JavaClassLoader extends ClassLoader {
    
        private File classPathFile;
    
        public JavaClassLoader(){
    //        String classPath=JavaClassLoader.class.getResource("").getPath();
            String classPath="D:\\code";
            this.classPathFile=new File(classPath);
        }
    
        @Override
        public Class<?> findClass(String name) throws ClassNotFoundException {
            String className= JavaClassLoader.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(in!=null){
                          try {
                              in.close();
                          } catch (IOException e) {
                              e.printStackTrace();
                          }
                      }
                      if(out!=null){
                          try {
                              out.close();
                          } catch (IOException e) {
                              e.printStackTrace();
                          }
                      }
                  }
              }
            }
            return null;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    public class MyJdkInvocationHandler implements MayiktJdkInvocationHandler {
        /**
         * 目标对象
         */
        private Object target;
    
        public MyJdkInvocationHandler(Object target) {
            this.target = target;
        }
    
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            System.out.println("使用Jdk动态代理打印日志开始" + args[0]);
            Object result = method.invoke(target, args);
            System.out.println("使用Jdk动态代理打印日志结束" + args[1]);
            return result;
        }
    
    
        public <T> T getProxy() {
            return (T) MyProxy.newProxyInstance(new JavaClassLoader(), target.getClass().getInterfaces()[0], this);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    JDK动态代理总结

    JDK动态代理是基于我们接口的形式来实现代理的

    1.JDK动态代理生成代理类(Proxy(自增))
    2.调用addOrder方法时(Proxy0 中的 addOrder方法)
    3.Proxy0#addOrder JdkInvocationHandler# invoke
    4.直接通过反射机制调用到目标方法(传递目标对象)
    JDK动态代理 执行目标方法比CGLIB执行

    目标方法简单非常多。

    CGLIB动态代理
    利用asm字节码技术,生成子类实现对目标方法实现增强

    CGLIB动态代理与JDK动态代理实现原理思想都是差不多
    CGLIB JDK动态代理

    1.程序在运行时自动生成代理类.class
    2.类加载器机制将该class读取到程序中;
    3.执行目标方法—

    实现方式
    Maven依赖


    cglib
    cglib
    3.2.12

    核心代码

    public class CglibMethodInterceptor implements MethodInterceptor {
        public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
            System.out.println("<<<<<日志收集开始...>>>>>>>");
            Object reuslt = proxy.invokeSuper(obj, args);
            System.out.println("<<<<<日志收集结束...>>>>>>>");
            return reuslt;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "D:\\code");
    CglibMethodInterceptor cglibMethodInterceptor = new CglibMethodInterceptor();
    Enhancer enhancer = new Enhancer();
    // 设置代理类的父类
    enhancer.setSuperclass(MemberServiceImpl.class);
    // 设置回调对象
    enhancer.setCallback(cglibMethodInterceptor);
    // 创建代理对象
    MemberServiceImpl orderServiceImpl = (MemberServiceImpl) enhancer.create();
    orderServiceImpl.getMember();
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    Cglib动态代理底层源码分析

    CGLIB底层生成class -3个;
    JDK动态代理生成class --1个;

    OrderServiceImpl E n h a n c e r B y C G L I B EnhancerByCGLIB EnhancerByCGLIBe5d00400 CGLIB动态代理
    生成的 代理类
    OrderServiceImpl F a s t C l a s s B y C G L I B FastClassByCGLIB FastClassByCGLIB6d79ead4 ## 目标对象中
    目标方法 对应的fastclass 索引 index
    OrderServiceImpl E n h a n c e r B y C G L I B EnhancerByCGLIB EnhancerByCGLIBe5d00400 F a s t C l a s s B y C G L I B FastClassByCGLIB FastClassByCGLIB36b9e032
    Cglib代理方法 CGLIB$addOrder$0 对应的fastclass 索引 index

    1.cglib 动态代理生成的代理类 继承目标对象
    2.jdk动态代理生成的代理类 实现了目标对象所实现的接口
    jdk动态代理 基于目标对象的接口实现代理
    cglib 动态代理 直接 继承我们 目标对象实现代理

    cglib动态代理 底层实现原理

    1.cglib动态代理 在生成代理类的class 时,
    2.通过代理类的 setCallback 传递我们开发者自己定义好的 CGLIBMethodInterceptor

    2.当我们调用到代理类中#addOrder方法时

    // 1.获取到 CGLIBMethodInterceptor
    MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
    if (var10000 == null) {
        CGLIB$BIND_CALLBACKS(this);
        var10000 = this.CGLIB$CALLBACK_0;
    }
    
    if (var10000 != null) {
        //2.执行CGLIBMethodInterceptor 的intercept方法
        var10000.intercept(this, CGLIB$addOrder$0$Method, new Object[]{var1, var2}, CGLIB$addOrder$0$Proxy);
    } else {
        super.addOrder(var1, var2);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    CGLIB不是基于反射机制调用(C编写的)到目标方法而是通过
    Fastclass 索引的机制(java实现)
    反射机制调用目标方法 -----一行

    CGLIB 生成的代理 调用我们的目标方法 Fastclass 建立索引机制
    直接调用我们的目标方法(class文件体现)

    Fastclass 如何执行到目标方法:

    private static class FastClassInfo
    {
        FastClass f1; ###  OrderServiceImpl$$FastClassByCGLIB$$6d79ead4 目标对象中 目标方法 对应fastclass
    FastClass f2;  ###  OrderServiceImpl$$EnhancerByCGLIB$$e5d00400$$FastClassByCGLIB$$36b9e032
        int i1; ###  addOrder(Ljava/lang/String;Ljava/lang/Integer;)V 目标方法 在
    Fastclass 中对应的 index;
        int i2; ## CGLIB$addOrder$0   CGLIB代理方法
    }
    fci.i1 = fci.f1.getIndex(sig1); OrderServiceImpl$$FastClassByCGLIB$$6d79ead4#getIndex方法
    fci.i2 = fci.f2.getIndex(sig2);OrderServiceImpl$$EnhancerByCGLIB$$e5d00400$$FastClassByCGLIB$$36b9e032
    #getIndex方法
    
    
    
    
    
    OrderServiceImpl$$EnhancerByCGLIB$$e5d00400###cglib生成的代理类;
    OrderServiceImpl$$FastClassByCGLIB$$6d79ead4 ###CglibFastClass 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    Cglib依赖于ASM字节码技术,直接生成class文件,在采用类加载器读取到程序中,
    使用fastclass对被代理类的方法建立索引文件不需要依赖于反射查找到目标方法
    CGLIB 早期 发现 如果反射技术调用目标方法效率非常低,
    想能够实现直接类似于 开发者 java代码的形式调用目标方法提高效率。

    public class OrderServiceImpl$$EnhancerByCGLIB$$1dd3a71c extends OrderServiceImpl {
    
        static void CGLIB$STATICHOOK1() throws ClassNotFoundException {
            Method amethod[];
            Method amethod1[];
            CGLIB$THREAD_CALLBACKS = new ThreadLocal();
            CGLIB$emptyArgs = new Object[0];
            Class class1 = Class.forName("com.mayikt.service.impl.OrderServiceImpl$$EnhancerByCGLIB$$1dd3a71c");
            Class class2;
            amethod = ReflectUtils.findMethods(new String[]{
                    "addOrder", "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;"
            }, (class2 = Class.forName("com.mayikt.service.impl.OrderServiceImpl")).getDeclaredMethods());
            Method[] _tmp = amethod;
            CGLIB$addOrder$0$Method = amethod[0];
            CGLIB$addOrder$0$Proxy = MethodProxy.create(class2, class1, "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;", "addOrder", "CGLIB$addOrder$0");
            amethod1 = ReflectUtils.findMethods(new String[]{
                    "equals", "(Ljava/lang/Object;)Z", "toString", "()Ljava/lang/String;", "hashCode", "()I", "clone", "()Ljava/lang/Object;"
            }, (class2 = Class.forName("java.lang.Object")).getDeclaredMethods());
            Method[] _tmp1 = amethod1;
            CGLIB$equals$1$Method = amethod1[0];
            CGLIB$equals$1$Proxy = MethodProxy.create(class2, class1, "(Ljava/lang/Object;)Z", "equals", "CGLIB$equals$1");
            CGLIB$toString$2$Method = amethod1[1];
            CGLIB$toString$2$Proxy = MethodProxy.create(class2, class1, "()Ljava/lang/String;", "toString", "CGLIB$toString$2");
            CGLIB$hashCode$3$Method = amethod1[2];
            CGLIB$hashCode$3$Proxy = MethodProxy.create(class2, class1, "()I", "hashCode", "CGLIB$hashCode$3");
            CGLIB$clone$4$Method = amethod1[3];
            CGLIB$clone$4$Proxy = MethodProxy.create(class2, class1, "()Ljava/lang/Object;", "clone", "CGLIB$clone$4");
        }
    
        final String CGLIB$addOrder$0(String s, String s1) {
            return super.addOrder(s, s1);
        }
    
    
        final boolean CGLIB$equals$1(Object obj) {
            return super.equals(obj);
        }
    
    
        final String CGLIB$toString$2() {
            return super.toString();
        }
    
    
        final int CGLIB$hashCode$3() {
            return super.hashCode();
        }
    
    
        public static void CGLIB$SET_THREAD_CALLBACKS(Callback acallback[]) {
            CGLIB$THREAD_CALLBACKS.set(acallback);
        }
    
        public final String addOrder(String paramString1, String paramString2) {
            MethodInterceptor tmp4_1 = this.CGLIB$CALLBACK_0;
            if (tmp4_1 == null) {
    
                CGLIB$BIND_CALLBACKS(this);
            }
            try {
                MethodInterceptor tmp17_14 = this.CGLIB$CALLBACK_0;
                if (tmp17_14 != null) {
                    return (String) tmp17_14.intercept(this, CGLIB$addOrder$0$Method, new Object[]{paramString1, paramString2}, CGLIB$addOrder$0$Proxy);
                }
            } catch (Throwable throwable) {
                throwable.printStackTrace();
            }
            return super.addOrder(paramString1, paramString2);
        }
    
    
        public Object newInstance(Callback acallback[]) {
            CGLIB$SET_THREAD_CALLBACKS(acallback);
            CGLIB$SET_THREAD_CALLBACKS(null);
            return new OrderServiceImpl$$EnhancerByCGLIB$$1dd3a71c();
        }
    
        public Object newInstance(Callback callback) {
            CGLIB$SET_THREAD_CALLBACKS(new Callback[]{
                    callback
            });
            CGLIB$SET_THREAD_CALLBACKS(null);
            return new OrderServiceImpl$$EnhancerByCGLIB$$1dd3a71c();
        }
    
    
        public void setCallback(int i, Callback callback) {
            switch (i) {
                case 0: // '\0'
                    CGLIB$CALLBACK_0 = (MethodInterceptor) callback;
                    break;
            }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
        private boolean CGLIB$BOUND;
        public static Object CGLIB$FACTORY_DATA;
        private static ThreadLocal CGLIB$THREAD_CALLBACKS = null;
        private static final Callback CGLIB$STATIC_CALLBACKS[] = null;
        private MethodInterceptor CGLIB$CALLBACK_0;
        private static Object CGLIB$CALLBACK_FILTER;
        private static Method CGLIB$addOrder$0$Method = null;
        private static MethodProxy CGLIB$addOrder$0$Proxy = null;
        private static Object[] CGLIB$emptyArgs = null;
        private static Method CGLIB$equals$1$Method = null;
        private static MethodProxy CGLIB$equals$1$Proxy = null;
        private static Method CGLIB$toString$2$Method = null;
        private static MethodProxy CGLIB$toString$2$Proxy = null;
        private static Method CGLIB$hashCode$3$Method = null;
        private static MethodProxy CGLIB$hashCode$3$Proxy = null;
        private static Method CGLIB$clone$4$Method = null;
        private static MethodProxy CGLIB$clone$4$Proxy = null;
    
        static {
            try {
                CGLIB$STATICHOOK1();
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
        }
    
        public OrderServiceImpl$$EnhancerByCGLIB$$1dd3a71c() {
            CGLIB$BIND_CALLBACKS(this);
        }
    
        private void CGLIB$BIND_CALLBACKS(OrderServiceImpl$$EnhancerByCGLIB$$1dd3a71c orderServiceImpl$$EnhancerByCGLIB$$1dd3a71c) {
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33

    FastClass机制

    public class MayiktFastclass {
    
        /**
         * 根据索引查找到目标方法
         *
         * @param index
         * @param obj
         * @param args
         * @return
         */
        public static Object invoke(int index, Object obj, Object[] args) {
            OrderServiceImpl orderService = (OrderServiceImpl) obj;
            switch (index) {
                case 1:
                    return orderService.addOrder(String.valueOf(args[0]), String.valueOf(args[1]));
            }
            return null;
        }
    
        /**
         * 根据签名索引文件
         *
         * @param sign
         * @return
         */
        public static int getIndex(String sign) {
            switch (sign.hashCode()) {
                case 1763340254:
                    return 1;
                case 20:
                    return 2;
            }
            return -1;
        }
    
        public static void main(String[] args) {
            System.out.println("addOrder()String,String".hashCode());
            Object result = invoke(getIndex("addOrder()String,String"), new OrderServiceImpl(), new String[]{"mayikt", "meite"});
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40

    Jdk与Cglib动态代理的区别
    1.Jdk动态代理利用反射技术生成匿名的代理类走InvokeHandler回调方法实现增强,同时也是一种基于接口的方式实现代理。
    2.Cglib动态代理利用asm字节码技术生成一个子类覆盖其中的方法实现增强,同时采用fastClass机制对整个代理类建立索引调用目标方法
    3.在Spring中如果需要被代理的对象如果实现了接口采用Jdk动态代理,没有实现接口则使用Cglib动态代理。
    代理模式常见面试题

    JDK动态代理与CGLIB动态代理那个效率高?
    名称 只生成class(毫秒) 生成class+调用目标方法(毫秒)
    Cglib代理(三个class文件) 104 133(目标方法29毫秒)
    JDK动态代理(一个class) 14 30(16毫秒左右)
    测试环境JDK8
    Cglib代理----根据fastclass机制调用目标方法 (目标方法29毫秒)
    JDK代理 反射机制调用目标方法 (16毫秒左右)
    根据fastclass机制调用目标方法代理 比我们反射调用目标方法 高2倍左右

    相关测试代码:

    package com.mayikt;
    
    import com.mayikt.proxy.CglibMethodInterceptor;
    import com.mayikt.proxy.JdkInvocationHandler;
    import com.mayikt.service.OrderService;
    import com.mayikt.service.OrderServiceImpl;
    import net.sf.cglib.proxy.Enhancer;
    
    /**
     * @author 余胜军
     * @ClassName Test05
     * @qq 644064779
     * @addres www.mayikt.com
     * 微信:yushengjun644
     */
    public class Test05 {
        public static void main(String[] args) {
            // cglib 与JDK动态代理 效率测试
            cglibProxy();
        }
    
        public static void jdkProxy() {
            Long start = System.currentTimeMillis();
            for (int i = 0; i < 1000; i++) {
                JdkInvocationHandler jdkInvocationHandler =
                        new JdkInvocationHandler(new OrderServiceImpl());
                OrderService orderService = jdkInvocationHandler.getProxy();// 代理类
                // orderService.addOrder("mayikt", 22);
            }
            Long end = System.currentTimeMillis();
            System.out.println("总共花费时间:" + (end - start));
        }
    
        public static void cglibProxy() {
            Long start = System.currentTimeMillis();
            for (int i = 0; i < 1000; i++) {
                // 1.new CglibMethodInterceptor
                CglibMethodInterceptor cglibMethodInterceptor = new CglibMethodInterceptor();
                // 2.enhancer
                Enhancer enhancer = new Enhancer();
                //3.设置代理类 父类class
                enhancer.setSuperclass(OrderServiceImpl.class);
    //        //4.设置回调
                enhancer.setCallback(cglibMethodInterceptor);
                //5.创建代理对象
                OrderServiceImpl orderServiceImpl = (OrderServiceImpl) enhancer.create();
               // orderServiceImpl.addOrder("mayikt", 22);
            }
            Long end = System.currentTimeMillis();
            System.out.println("总共花费时间:" + (end - start));
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52

    JDK6 中 Jdk动态代理比CGLIB 效率低;
    JDK8中CGLIB动态代理比jdk动态低5-10倍。

    Spring使用的是CGLIB还是JDK动态代理
    Cglib 基于 目标对象 类实现继承的形式 采用 fastclass 机制调用目标方法

    JDK动态代理基于 目标对象类 实现接口 代理 采用反射机制调用目标方法
    Spring判断 如果目标对象 实现接口的话 采用JDK动态代理
    如果 如果目标对象 类没有实现接口的话 则采用 CGLIB代理。
    JDK动态代理—实际的项目中采用JDK动态代理非常多
    ,程序员在编写代码的过程中 使用 接口的形式比较多。

  • 相关阅读:
    ComfyUI 安装
    会计基础——公式汇总
    使用Jitpack发布开源Java库
    HTML5期末大作业:基于HTML+CSS+JavaScript仿蘑菇街购物商城设计毕业论文源码
    Linux-Centos中配置docker
    计算机网络常见面试题
    除静电离子风刀的工作原理及应用
    仪表盘自定义标题和数值样式
    点云从入门到精通技术详解100篇-散乱点云法向量估计
    docker 本地保存镜像方法--docker export 和docker save 使用介绍
  • 原文地址:https://blog.csdn.net/u014001523/article/details/125457182