Java动态代理的两种实现方式

动态代理是为了实现在不改变源码的基础上,对已有方法增强,它是AOP思想的底层实现技术。一般而言,动态代理有以下两种实现方式

一、基于接口的动态代理(JDK动态代理)

要求:被代理类最少实现一个接口
提供者:jdk官方
例:

/**
 * 演员类
 */
public class Actor implements IActor{
    public void basicAct(float money){
        System.out.println("拿到"+money+"钱,开始初级表演");
    }
    public void advancedAct(float money){
        System.out.println("拿到"+money+"钱,开始高级表演");
    }
}
/**
 * 演员类要实现的接口,即标准
 */
public interface IActor {
    public void basicAct(float money);
    public void advancedAct(float money);
}
/**
 * 剧组类,主方法
 */
public class Client {
    public static void main(String[] args) {
        final Actor actor = new Actor();
        /**
         * 剧组找演员,通过经纪公司,它就是代理
         * 涉及的类:Proxy
         * 创建代理对象的方法:newProxyInstance()
         * 该方法的参数:
         *      ClassLoader:;类加载器。和被代理对象使用相同的类加载器
         *      Class[]:字节码数组。被代理类实现的接口,要求代理对象和被代理对象具有相同的行为
         *      InvocationHandler:用于我们提供增强代码的接口。一般会写一个该接口的实现类。
         *                        实现类可以是匿名内部类。它的含义就是如何代理。这里的代码只能是谁用谁提供
         */
        IActor proxyActor = (IActor) Proxy.newProxyInstance(actor.getClass().getClassLoader(),
                actor.getClass().getInterfaces(),
                new InvocationHandler() {
                    /**
                     * 执行被代理对象的任何方法都会经过该方法,该方法有拦截的功能
                     * Object proxy:代理对象的引用。不一定每次都会有
                     * Method method:当前执行的方法
                     * Object[] args:当前执行方法所需的参数
                     * @return 当前执行方法的返回值
                     */
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        Object ret=null;
                        //1.取出执行方法中的参数
                        Float money = (Float) args[0];
                        //2.判断当前执行的什么方法
                        if ("basicAct".equals(method.getName())){
                            if (money>10000)
                                ret = method.invoke(actor,money);
                        }
                        if ("advancedAct".equals(method.getName())){
                            if (money>50000)
                                ret = method.invoke(actor,money);
                        }
                        return ret;
                    }
                });
        proxyActor.basicAct(20000);
    }
}

二、基于子类的动态代理(Cglib动态代理)

要求:该代理类不能是最终类,不能被final修饰
提供者:第三方Cglib

改写上面的代码,此时Actor类不需要实现IActor接口

/**
 * 剧组类,主方法
 */
public class Client {
    public static void main(String[] args) {
        final Actor actor = new Actor();
        /**
         * 涉及的类:Enhancer
         * 创建代理对象的方法:create()
         * 该方法的参数:
         *        Class:被代理对象的字节码
         *        Callback:如何代理,作用同方法一的InvocationHandler
         */
        Actor proxyActor  = (Actor)Enhancer.create(actor.getClass(), new MethodInterceptor() {
            /**
             * 执行被代理对象的方法都会经过该方法,作用同方法一的invoke()
             * Object proxy:代理对象的引用。不一定每次都会有
             * Method method:当前执行的方法
             * Object[] args:当前执行方法所需的参数
             * MethodProxy methodProxy:当前执行方法的代理对象,一般不用
             * @return
             * @throws Throwable
             */
            public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
                Object ret=null;
                //1.取出执行方法中的参数
                Float money = (Float) args[0];
                //2.判断当前执行的什么方法
                if ("basicAct".equals(method.getName())){
                    if (money>10000)
                        ret = method.invoke(actor,money);
                }
                if ("advancedAct".equals(method.getName())){
                    if (money>50000)
                        ret = method.invoke(actor,money);
                }
                return ret;
            }
        });
        proxyActor.advancedAct(500000);
    }
}

你可能感兴趣的:(Java基础)