转载  JDK Proxy 和 CGLib 的使用及代码分析

分类:java,程序人生 2021-09-17T15:44:08    318人阅读   

1.JDK Proxy 和 CGLib 的使用及代码分析

JDK Proxy 动态代理实现

JDK Proxy 动态代理的实现无需引用第三方类,只需要实现 InvocationHandler 接口,重写 invoke() 方法即可,整个实现代码如下所示:

import java.lang.reflect.InvocationHandler;

import java.lang.reflect.InvocationTargetException;

import java.lang.reflect.Method;

import java.lang.reflect.Proxy;



/**

 * JDK Proxy 相关示例

 */

public class ProxyExample {

    static interface Car {

        void running();

    }



    static class Bus implements Car {

        @Override

        public void running() {

            System.out.println("The bus is running.");

        }

    }



    static class Taxi implements Car {

        @Override

        public void running() {

            System.out.println("The taxi is running.");

        }

    }



    /**

     * JDK Proxy

     */

    static class JDKProxy implements InvocationHandler {

        private Object target; // 代理对象



        // 获取到代理对象

        public Object getInstance(Object target) {

            this.target = target;

            // 取得代理对象

            return Proxy.newProxyInstance(target.getClass().getClassLoader(),

                    target.getClass().getInterfaces(), this);

        }



        /**

         * 执行代理方法

         * @param proxy  代理对象

         * @param method 代理方法

         * @param args   方法的参数

         * @return

         * @throws InvocationTargetException

         * @throws IllegalAccessException

         */

        @Override

        public Object invoke(Object proxy, Method method, Object[] args)

                throws InvocationTargetException, IllegalAccessException {

            System.out.println("动态代理之前的业务处理.");

            Object result = method.invoke(target, args); // 执行调用方法(此方法执行前后,可以进行相关业务处理)

            return result;

        }

    }



    public static void main(String[] args) {

        // 执行 JDK Proxy

        JDKProxy jdkProxy = new JDKProxy();

        Car carInstance = (Car) jdkProxy.getInstance(new Taxi());

        carInstance.running();
}
}

以上程序的执行结果是:

动态代理之前的业务处理.
The taxi is running.

可以看出 JDK Proxy 实现动态代理的核心是实现 Invocation 接口,我们查看 Invocation 的源码,会发现里面其实只有一个 invoke() 方法,源码如下:

public interface InvocationHandler {

  public Object invoke(Object proxy, Method method, Object[] args)

          throws Throwable;

}

这是因为在动态代理中有一个重要的角色也就是代理器,它用于统一管理被代理的对象,显然 InvocationHandler 就是这个代理器,而 invoke() 方法则是触发代理的执行方法,我们通过实现 Invocation 接口来拥有动态代理的能力。

CGLib 的实现

在使用 CGLib 之前,我们要先在项目中引入 CGLib 框架,在 pom.xml 中添加如下配置:

<!-- https://mvnrepository.com/artifact/cglib/cglib -->

<dependency>

    <groupId>cglib</groupId>

    <artifactId>cglib</artifactId>

    <version>3.3.0</version>

</dependency>

CGLib 实现代码如下:

package com.lagou.interview;



import net.sf.cglib.proxy.Enhancer;

import net.sf.cglib.proxy.MethodInterceptor;

import net.sf.cglib.proxy.MethodProxy;



import java.lang.reflect.Method;



public class CGLibExample {



    static class Car {

        public void running() {

            System.out.println("The car is running.");

        }

    }



    /**

     * CGLib 代理类

     */

    static class CGLibProxy implements MethodInterceptor {

        private Object target; // 代理对象



        public Object getInstance(Object target) {

            this.target = target;

            Enhancer enhancer = new Enhancer();

            // 设置父类为实例类

            enhancer.setSuperclass(this.target.getClass());

            // 回调方法

            enhancer.setCallback(this);

            // 创建代理对象

            return enhancer.create();

        }



        @Override

        public Object intercept(Object o, Method method,

                                Object[] objects, MethodProxy methodProxy) throws Throwable {

            System.out.println("方法调用前业务处理.");

            Object result = methodProxy.invokeSuper(o, objects); // 执行方法调用

            return result;

        }

    }



    // 执行 CGLib 的方法调用

    public static void main(String[] args) {

        // 创建 CGLib 代理类

        CGLibProxy proxy = new CGLibProxy();

        // 初始化代理对象

        Car car = (Car) proxy.getInstance(new Car());

        // 执行方法

        car.running();

以上程序的执行结果是:

方法调用前业务处理.
The car is running.

可以看出 CGLib 和 JDK Proxy 的实现代码比较类似,都是通过实现代理器的接口,再调用某一个方法完成动态代理的,唯一不同的是,CGLib 在初始化被代理类时,是通过 Enhancer 对象把代理对象设置为被代理类的子类来实现动态代理的。因此被代理类不能被关键字 final 修饰,如果被 final 修饰,再使用 Enhancer 设置父类时会报错,动态代理的构建会失败。

支付宝打赏 微信打赏

如果文章对你有帮助,欢迎点击上方按钮打赏作者

服务器费用不足...

绿色农产品果蔬购物商店HTML主题

优雅而现代的企业和商业html模板

餐厅美食在线订餐HTML5站点模板

创意布局企业网络服务CSS模板

炫酷网状变形动画js特效

公司事件会议发布会网站模板

CSS3主页个人简历网页模板

互联网机构和SaaS服务网页模板

网站顶部导航带下拉的Navigation

五彩纸屑掉落动画的例子

5套WebApp模板管理后台界面

整个页面滚动切换Js插件

拖拽实现流程图Drawflow.js插件

CSS 3D盒子打开动画特效

牛奶和饼干css卡通图画

多用途的Alert弹出窗口Js插件

沙滩保卫小游戏js源码

21个着陆页HTML5和CSS3模板

HTML5/Canvas太空射击类小游戏源码

绿色环保种植农场网站Html5模板

服务器费用不足...
 工具推荐 更多»