zoukankan      html  css  js  c++  java
  • Java的动态代理

    动态代理常用的有两种方式

    注:以下以演员演出作为例子:1. 直接找演员表演;2. 找到中介后,由中介寻找演员演出(中介需赚取佣金)。(其实与租房是类似的,找房东直租和找中介租房两种方式。)

    基于接口的动态代理
      提供者:JDK 官方的 Proxy 类。
      要求:被代理类最少实现一个接口。
     
    - IActor.java
    public interface IActor {
        boolean baseAct(float money);  // 基础演出
        boolean dangerAct(float money);  // 危险演出
    }

    - Actor.java

    public class Actor implements IActor {
    
        @Override
        public boolean baseAct(float money) {
            System.out.println("基础演出收入:"+money);
            return true;
        }
    
        @Override
        public boolean dangerAct(float money) {
            System.out.println("危险演出收入:"+money);
            return true;
        }
    }

    - ProxyTest.java

    /**
     * 使用 JDK 官方的 Proxy 类创建代理对象
     * 基于接口的动态代理
     *  提供者:JDK 官方的 Proxy 类。
     *  要求:被代理类最少实现一个接口。
     */
    public class ProxyTest {
        public static void main(String[] args) {
            Actor actor = new Actor();
            IActor proxyActor = proxyFun(actor);
    
            actor.baseAct(1000);
            actor.dangerAct(10000);
            proxyActor.baseAct(1000);
            proxyActor.dangerAct(10000);
        }
    
    
        public static IActor proxyFun(Actor actor) {
            /*
             * 创建的方式:
             *   Proxy.newProxyInstance(三个参数)
             * 参数含义:
             *   ClassLoader:和被代理对象使用相同的类加载器。
             *   Interfaces:和被代理对象具有相同的行为。实现相同的接口。
             *   InvocationHandler:如何代理。
             */
            IActor proxyActor = (IActor) Proxy.newProxyInstance(
                    actor.getClass().getClassLoader(),
                    actor.getClass().getInterfaces(),
                    new InvocationHandler() {
                        /**
                         * 执行被代理对象的任何方法,都会经过该方法。因此有拦截功能。
                         * @param proxy: 代理对象的引用。
                         * @param method: 外部所调用的方法,已封装为方法对象。
                         * @param args: 外部调用方法时传递的参数列表。
                         * @return 执行该方法后的返回值
                         */
                        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                            String name = method.getName();
                            float money = (float) args[0];
                            Object rtValue = null;
                            if ("baseAct".equals(name)) {
                                rtValue = method.invoke(actor,money/2);
                            }
                            if ("dangerAct".equals(name)) {
                                rtValue = method.invoke(actor, money/2);
                            }
                            return rtValue;
                        }
                    }
            );
    
            return proxyActor;
        }
    }

    - 运行结果

     

    基于子类的动态代理
      提供者:第三方的 CGLib,如果报 asmxxxx 异常,需要导入 asm.jar。
      要求:被代理类不能用 final 修饰的类(最终类)。 
     
    - Actor.java
    public class Actor {
    
        public boolean baseAct(float money) {
            System.out.println("基础演出收入:"+money);
            return true;
        }
    
        public boolean dangerAct(float money) {
            System.out.println("危险演出收入:"+money);
            return true;
        }
    }

    - EnhancerTest.java

    /**
     * 使用 CGLib 的 Enhancer 类创建代理对象
     * 基于子类的动态代理
     *  提供者:第三方的 CGLib,如果报 asmxxxx 异常,需要导入 asm.jar。
     *  要求:被代理类不能用 final 修饰的类(最终类)。
     */
    public class EnhancerTest {
        public static void main(String[] args) {
            Actor actor = new Actor();
            Actor enhancerActor = EnhancerFun(actor);
    
            actor.baseAct(1000);
            actor.dangerAct(10000);
            enhancerActor.baseAct(1000);
            enhancerActor.dangerAct(10000);
        }
    
        public static Actor EnhancerFun(Actor actor) {
            /*
             * 创建的方式:
             *   Enhancer.create(Class, Callback)
             * 参数的含义:
             *   Class:被代理对象的字节码
             *   Callback:如何代理(使用MethodInterceptor接口实现类代理)。
             */
            Actor enhancerActor = (Actor) Enhancer.create(actor.getClass(), new MethodInterceptor() {
                /**
                 * 执行被代理对象的任何方法,都会经过该方法。因此有拦截功能。
                 * @param proxy: 代理对象的引用。
                 * @param method: 外部所调用的方法,已封装为方法对象。
                 * @param args: 外部调用方法时传递的参数列表。
                 * @param methodProxy: 当前执行方法的代理对象。
                 * @return 执行该方法后的返回值
                 */
                public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
                    String name = method.getName();
                    float money = (float) args[0];
                    Object rtValue = null;
                    if ("baseAct".equals(name)) {
                        rtValue = method.invoke(actor,money/2);
                    }
                    if ("dangerAct".equals(name)) {
                        rtValue = method.invoke(actor, money/2);
                    }
                    return rtValue;
                }
            });
            return enhancerActor;
        }
    }

    - 运行结果

     

  • 相关阅读:
    2018-2019-1 20165308 5317 5331 实验三 实时系统
    daima
    2018-2019-1 20165308 20165317 20165331 实验二 固件程序设计
    2018-2019-1 20165308 20165317 20165331 实验一 开发环境的熟悉
    2018 第三周 20165308 缓冲区溢出漏洞实验
    20165308 信息安全系统设计基础 第一周总结
    20165308 2017-2018-2 《Java程序设计》课程总结
    2017-2018-2 20165308 实验五《网络编程与安全》实验报告
    2018-2019-2 20165320 《网络对抗技术》 Exp6 信息搜集与漏洞扫描
    2018-2019-2 网络对抗技术 20165320 Exp5 MSF基础应用
  • 原文地址:https://www.cnblogs.com/q10040/p/13056016.html
Copyright © 2011-2022 走看看