动态代理

常见的动态代理实现主要有两种方法:

一、jdk动态代理,被代理对象必须是基于接口,使用Proxy中的newProxyInstanc()方法

二、cglib动态代理,被代理类不能是最终类(final修饰的类),因为cglib实现的动态代理是基于子类实现的,需要引入第三方jar包cglib,cglib依赖asm,使用EnHancer.create()方法,代码中有介绍

jdk生成动态代理的类:

public class ProxyTool {

    /**
     *  需要被代理的类
     */
    private Object obj;
    public ProxyTool(Object obj){
        this.obj = obj;
    }

    /**
     * Proxy.newProxyInstance()方法有三个参数:
     * ClassLoader:用于加载代理对象的字节码,与被代理对象的类加载器保持一致,固定写法
     * Class[]:字节码数据,用于让代理类与被代理类有相同的方法,固定写法
     * InvocationHandler: 用于提供增强的代码,InvocationHandler接口中有一个方法 invoke()
     *
     *
     * invoke中有三个参数:
     * proxy:代理对象
     * method:当前执行的方法
     * args:当前执行方法的参数
     * @return
     */
    public Object getProxy(){
        return Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(),
                new InvocationHandler() {
                    public Object invoke(Object proxy, Method method, Object[] args) throws InvocationTargetException, IllegalAccessException {
                       //写增强代码的地方
                        System.out.println("动态代理生效");
                        return method.invoke(obj,args);
                    }
                });

    }
}
View Code

cglib生成动态代理:

public class CglibProxy {
    /**
     * 被代理对象
     */
    private Object obj;
    public CglibProxy(Object obj){
        this.obj = obj;
    }

    /**
     * 获取代理对象方法
     * 使用cglib中Enhancer.create()方法,
     * create()方法有两个参数
     * Class:字节码,被代理对象的字节码
     * Callback;用于写增强代码的接口,一般用其子接口MethodInterceptor
     *
     *
     * @return
     */
    public Object getProxy(){
        return Enhancer.create(obj.getClass(), new MethodInterceptor() {
            /**
             *注意:intercept()方法中形参的名称o是指代理对象
             * @param o      代理对象
             * @param method  当前执行的方法
             * @param objects  当前执行方法的参数
             * @param methodProxy  当前执行方法的代理对象
             * @return
             * @throws Throwable
             */
            public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
                //写增强的代码
                System.out.println("动态代理开启,这是cglib代理");
                return method.invoke(obj,objects);
            }
        });

    }
}
View Code

测试类:

public class Main {
    public static void main(String[] args) {
        //被代理对象
        IProxyImpl proxy1 = new IProxyImpl();
        //代理工具
        //ProxyTool ProxyTool = new ProxyTool(proxy1);
        CglibProxy cglibProxy = new CglibProxy(proxy1);
        //获取到代理类,当为jdk代理时不能用用实现类来强转
        IProxy proxy = (IProxy)cglibProxy.getProxy();

        //执行方法
        proxy.print();
    }
}
View Code

 使用动态代理时,若被代理的方法抛出异常,代理对象也会抛出异常,但是异常不是原来的异常;

 该异常可参考这篇文章:https://www.cnblogs.com/zhaolei1996/p/12435256.html

心有多大,天有多高,一起奋斗!!
原文地址:https://www.cnblogs.com/zhaolei1996/p/12423837.html