• Java动态代理(JDK和Cglib)


    动态代理

    代理模式,是为其他对象提供一个代理来控制对某个真实对象的访问。代理类负责对调用的消息进行处理和转发,以及在委托类执行后的一些后续操作的处理。代理类似一个演员的经纪人,负责对所有的活动进行筛选和过滤,并且将消息转发给该演员,在演员演出后,负责做一些收尾工作。

    动态代理,它在静态代理的基础上又迈进了一步。可以动态的创建代理,并且动态的处理对所代理方法的调用。动态代理则分为以下两种:
    - 1、JDK动态代理:
    - 基于接口进行代理 (必须实现接口)
    - 2、Cglib动态代理:
    - 基于继承进行代理 原理为继承要代理的类,并Override其中的方法实现代理

    JDK动态代理

    动态代理的使用方法如下:

    • 实现InvocationHandler完成自己的调用处理器
    • 通过Proxy.newProxyInstance()来创建动态代理,该方法需要的到三个参数,
      • 一个类加载器(可从已被加载的对象中获取)
      • 代理实现的接口列表
      • 以及InvocationHandler接口的一个实现,并传递给处理器一个实际对象。
    • 通过代理对象来调用请求

    这样,外部的所有调用请求,就都会重定向到调用处理器,在经过处理器的调用,通过Method.invoke()转发给委托对象。这样就可以简单实现了对方法调用的拦截和过滤。

    /**
     * 定义一个接口并实现
     */
    interface Interface {
        void doSomething();
    }
    
    class Real implements Interface {
        public void doSomething(String arg) {
            Sytstem.out.println("dosomething  " + arg);
        }
    }
    import java.lang.reflect.*;
    
    /**
     * 实现InvocationHandler接口
     * 完成自定义的调用处理器
     */
    class MyProxyHandler implements InvocationHandler {
        //被代理对象
        private Object proxied;
        public MyProxyHandler(Object proxied) {
            this.proxied = proxied;
        }
    
        public Object invoke(Object object, Method method, Object[] args)
        throws Throwable {
            System.out.println("****before:" + method + "****");
            method.invoke(proxied, args);
            System.out.println("****after:" + method + "****");
        }
    }
    
    /**
     * 通过Proxy.newProxyInstance()方法获取动态代理
     * 使用代理调用方法
     */
    class DynamicProxy {
        public static void main(String[] args) {
            Real real = new Real();
            Interface proxy = (Interface)Proxy.newProxyInstance(
              Interface.class.getClassLoader(),
              new Class[]{ Interface.class },
              new MyProxyHandler(real);
            )
            proxy.doSomething("hello");
        }
    }

    Cglib动态代理

    Chlib动态代理使用主要有如下几点:

    • 实现MethodInterceptor,完成拦截的切面处理
      • 通过methodProxy.invokeSuper(obj, args);来调用被代理的方法
    • 通过实例化的Enhancer生成代理对象,实例化步骤如下:
      • 实例化Enhancer:Enhancer enhancer = new Enhancer();
      • 设置被代理的基类:enhancer.setSuperClass(clz);
      • 设置回调函数,即是实现的切面:enhancer.setCallback(methodInterceptor);
      • 创建代理对象:enhancer.create();
    • 使用生成的代理对象完成调用
    public class MyInterceptor implements MethodInterceptor {
        @Override
        public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
            System.out.println("#####before######");
            Object result = null;
            try {
                result = methodProxy.invokeSuper(o, objects);
            } catch (Throwable e) {
                System.out.println(e.getMessage());
                throw e;
            }
            System.out.println("#####after#####");
            return result;
        }
    
        public static void main(String[] args) {
            BaseObject proxyObj = (BaseObject)getProxyObj(RealObject.class, new MyInterceptor());
            proxyObj.method();
        }
    
        public static Object getProxyObj (Class clz, MethodInterceptor callback) {
            Enhancer enhancer = new Enhancer();
            return enhancer.create(clz, callback);
        }
    }
    
    abstract class BaseObject {
        public abstract void method();
    }
    
    class RealObject extends BaseObject {
    
        @Override
        public void method() {
            System.out.println("real obj was called!!!");
        }
    }
  • 相关阅读:
    web service--基础概念(1)
    java web--国际化 i18n
    洛谷 P3842 [TJOI2007]线段
    洛谷 P6205 [USACO06JAN]Dollar Dayz S
    洛谷 P5414 [YNOI2019]排序
    洛谷 P1681 最大正方形II
    洛谷 P2327 [SCOI2005]扫雷
    洛谷 P1373 小a和uim之大逃离
    洛谷 P4317 花神的数论题
    洛谷 P4127 [AHOI2009]同类分布
  • 原文地址:https://www.cnblogs.com/enhe/p/12141698.html
Copyright © 2020-2023  润新知