用途

当现有的类的代码只能满足一些基本的功能,而这些功能满足不了新需求,但又不能改动以前的代码,这时候就可以考虑使用代理,通过代理类,扩展原有类的功能,客户端访问的入口只是从目标对象切换到代理对象而已;

jdk代理

JDK 动态代理是基于拦截器和反射实现的,不需要第三方库支持,只需要 JDK 环境即可

  • 必须实现 InvocationHandler 接口;
  • 使用 Proxy.newProxyInstance 产生代理对象;
  • 被代理的对象必须要实现接口;
  • 内部采用asm技术动态生成字节码;
public class JdkProxyDemo {

    interface Foo{
        void show();
    }

    static class Target implements Foo{
        @Override
        public void show() {
            System.out.println("show");
        }
    }

    static class JdkInvocationHandler implements InvocationHandler{
        private Foo foo;
        public JdkInvocationHandler(Foo foo){
            this.foo=foo;
        }
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            System.out.println("before");
            Object result = method.invoke(foo, args);
            //代理类返回的是目标方法执行的结果
            System.out.println("after");
            return result;
        }
    }
    /**
     * jdk代理只能针对接口进行代理
     * 内部采用asm技术动态生成字节码()
     * @param args
     */
    public static void main(String[] args) {
        ClassLoader classLoader = JdkProxyDemo.class.getClassLoader();
        InvocationHandler handler = new JdkInvocationHandler(new Target());
        Foo proxy = (Foo) Proxy.newProxyInstance(classLoader, new Class[]{Foo.class},handler);
        proxy.show();
    }
}

cglib代理

JDK实现动态代理需要实现类通过接口定义业务方法,对于没有接口的类,如何实现动态代理呢,这就需要cglib了;

cglib采用了非常底层的字节码技术,其原理是通过字节码技术为一个类创建子类,并在子类中采用方法拦截的技术拦截所有父类方法的调用,顺势织入横切逻辑。

/**
 * cglib代理是通过父子继承关系创建代理
 * 代理对象自身是作为一个子类型的存在
 */
public class CglibProxyDemo {
    static class Target {
        public void show() {
            System.out.println("show");
        }
    }

    public static void main(String[] args) {
        Target target = new Target();
        Callback callback = new MethodInterceptor() {
            // o : 代理类对象自身
            //method : 代理类执行的方法
            //args : 方法执行参数
            //methodProxy :  方法代理【采用这个参数,可以避免使用方法反射进行调用,但是内部未使用反射】
            @Override
            public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {

               /* 基于反射实现
               System.out.println("before");
                Object result = method.invoke(target, args);
                System.out.println("after");
                return result;*/

                //methodProxy 使用 ,使用目标进行代理
                /*System.out.println("before");
                Object result = methodProxy.invoke(target,args);
                System.out.println("after");
                return result;*/

                //methodProxy 使用 ,使用自身进行代理
                System.out.println("before");
                Object result = methodProxy.invokeSuper(o,args);
                System.out.println("after");
                return result;

            }
        };
        Target proxy = (Target) Enhancer.create(Target.class, callback);
        proxy.show();
    }
}

参考:https://blog.csdn.net/zhangcongyi420/article/details/125351123