zoukankan      html  css  js  c++  java
  • 【DP-动态代理】JDK&Cglib

     

    需求:增强未知方法的代码

    简单方案:继承或者聚合

    1. 继承,调用方法前后加增强逻辑

    2. 聚合 - 静态代理

      1. 持有被代理类对象 或者接口

      2. 可通过嵌套实现代理的组合 和 装饰器模式很像

    高级方案

    • 代理所有的类,不只是某一类的接口,静态的聚合方式成员属性是具体的
    JDK 动态代理 
    package club.interview.design_pattern.chapt6_proxy;
    
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    import java.lang.reflect.Proxy;
    
    /**
     * @author QuCheng on 2020/6/15.
     */
    public interface Vegetable {
    
        void growUp();
    
        class Cabbage implements Vegetable {
    
            @Override
            public void growUp() {
                System.out.println("卷心菜慢慢长大");
            }
        }
    
        class LogProxy implements InvocationHandler {
    
            Object o;
    
            public LogProxy(Object o) {
                this.o = o;
            }
    
            public static Object getProxy(Object object) {
                System.getProperties().setProperty("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");
                return Proxy.newProxyInstance(object.getClass().getClassLoader(),
                        object.getClass().getInterfaces(), new LogProxy(object));
            }
    
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                System.out.println("good goods study");
                Object invoke = method.invoke(o, args);
                System.out.println("day day up");
                return invoke;
            }
    
            public static void main(String[] args) {
                Vegetable v = (Vegetable) LogProxy.getProxy(new Cabbage());
                v.growUp();
            }
        }
    
    } 
    • proxy源码解读
      • 实际产生的对象是$Proxy0.class的对象,继承proxy,实现目标接口方法
      • 执行目标接口时实际调用super也就是proxy的InvokationHandler的invoke对象
    • 生成代理源码解读Proxy.newInstance(...)
      • 跟进去会发现底层是利用asm动态生成二进制文件$Proxy0.class 
    Cglib
    package club.interview.design_pattern.chapt6_proxy;
    ​
    import net.sf.cglib.proxy.Enhancer;
    import net.sf.cglib.proxy.MethodInterceptor;
    import net.sf.cglib.proxy.MethodProxy;
    ​
    import java.lang.reflect.Method;
    ​
    /**
     * @author QuCheng on 2020/6/15.
     */
    public class CabbageCglib {
    ​
        public void growUp() {
            System.out.println("卷心菜慢慢长大");
        }
    ​
        static class LogProxyCglib implements MethodInterceptor {
    ​
            @SuppressWarnings("unchecked")
            static <T> T getProxy(T o) {
                Enhancer enhancer = new Enhancer();
                enhancer.setSuperclass(o.getClass());
                enhancer.setCallback(new LogProxyCglib());
                return (T) enhancer.create();
            }
    ​
            @Override
            public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
                System.out.println("good good study");
                // invokeSuper not invoke
                Object invoke = methodProxy.invokeSuper(o, objects);
                System.out.println("day day up");
                return invoke;
            }
        }
    ​
        public static void main(String[] args) {
    ​
            CabbageCglib cabbageCglib = LogProxyCglib.getProxy(new CabbageCglib());
            cabbageCglib.growUp();
        }
    }
    两种动态代理对比
    • jdk

      • 优点:jdk原生,可代理有接口实现的类

      • 缺点:代理类必须实现接口

    • cglib

      • 优点:

        • 被代理类无需实现接口

        • 实现简单,无需聚合

      • 缺点:因为是采用继承,被代理类不能被final修饰

  • 相关阅读:
    前端框架-Bootstrap【搭建后台管理系统】
    前端-jQuery
    前端-js基础语法-DOM
    前端-js基础语法
    前端-html标签
    python学习并发编程
    python学习网络编程
    python爬虫学习:第一爬_快眼看书排行榜
    python总结:模块汇总
    python学习_解释器接口模块:sys
  • 原文地址:https://www.cnblogs.com/nightOfStreet/p/13141326.html
Copyright © 2011-2022 走看看