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;
    }
}

- 运行结果

 

原文地址:https://www.cnblogs.com/q10040/p/13056016.html