博客
关于我
Java--代理
阅读量:285 次
发布时间:2019-03-01

本文共 3613 字,大约阅读时间需要 12 分钟。

Java动态代理详解

代理的概念

代理是一种常见的设计模式,旨在在不修改源代码的情况下对目标类的方法进行增强或扩展。在Java中,代理可以分为静态代理和动态代理两种形式。本文将重点介绍动态代理的实现方式及其应用场景。


动态代理的实现原理

动态代理通过Proxy.newProxyInstance方法来创建接口代理对象。该方法的三个主要参数如下:

  • ClassLoader loader:指定用于加载代理类的类加载器。
  • Class<?>[] interfaces:指定被代理接口的类数组。
  • InvocationHandler h:指定一个动态代理的调用处理器(Invocation Handler),用于动态地处理被代理方法的调用。
  • 通过InvocationHandler,我们可以在不修改目标类源代码的情况下,动态地增强目标类的方法行为。


    动态代理的实现步骤

    1. 创建被代理接口

    假设我们有一个接口OneDao,其中定义了一个方法add(int a, int b)用于计算两个整数的和。以下是接口的定义:

    public interface OneDao {    public int add(int a, int b);}

    2. 创建被代理实现类

    接下来,我们创建一个实现OneDao接口的类OneDaoImpl。该类的实现如下:

    public class OneDaoImpl implements OneDao {    @Override    public int add(int a, int b) {        return a + b;    }}

    3. 定义Invocation Handler

    为了实现动态代理,我们需要定义一个InvocationHandler的实现类MyHandler。该类将负责动态地处理被代理方法的调用。以下是MyHandler的实现:

    class MyHandler implements InvocationHandler {    private Object object; // 被代理对象    public MyHandler(Object object) {        this.object = object;    }    @Override    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {        System.out.println("方法前:" + method.getName());        Object result = method.invoke(object, args);        System.out.println("方法后:" + method.getName());        return result;    }}

    4. 创建代理对象

    通过Proxy.newProxyInstance方法,我们可以根据指定的接口和调用处理器创建一个动态代理对象。以下是创建代理对象的代码示例:

    @Testpublic void method() {    OneDaoImpl oneDao = new OneDaoImpl();    OneDao dao = (OneDao) Proxy.newProxyInstance(OneDaoImpl.class.getClassLoader(),         new Class[]{OneDaoImpl.class},         new MyHandler(oneDao)    );    int add = dao.add(1, 2);    System.out.println(add);}

    5. 调用代理对象

    通过上述代码,我们可以看到动态代理对象dao实际上是通过MyHandler来调用OneDaoImpl类的方法。每当调用dao.add(1, 2)时,MyHandler都会先输出日志,执行目标方法oneDao.add(1, 2),然后再输出日志。


    动态代理的优势

    动态代理的主要优势在于它能够在不修改目标类源代码的情况下,动态地增强目标类的方法行为。这种特性在以下场景尤为有用:

  • 日志记录:可以在方法执行前后记录日志。
  • 性能监控:可以在方法执行过程中监控性能参数。
  • 安全性:可以在方法执行前后进行权限检查或其他安全验证。
  • 功能扩展:可以在不修改目标类的情况下,扩展方法功能。

  • 实际应用示例

    假设我们有一个Human接口,定义了两个方法getAge()getName()。我们可以通过动态代理来增强这些方法的行为。

    被代理类

    public class GDPeople implements Human {    private int age;    private String name;    public GDPeople(int age, String name) {        this.age = age;        this.name = name;    }    @Override    public int getAge() {        return age;    }    @Override    public String getName() {        return name;    }}

    代理工厂

    我们可以创建一个ProxyFactory工厂类,用于生成动态代理对象。以下是ProxyFactory的实现:

    public class ProxyFactory {    public static Object getProxyInstance(Object obj) {        MyInvocationHandler handler = new MyInvocationHandler();        handler.bind(obj);        return Proxy.newProxyInstance(obj.getClass().getClassLoader(),             obj.getClass().getInterfaces(),             handler        );    }}class MyInvocationHandler implements InvocationHandler {    private Object object;    public void bind(Object object) {        this.object = object;    }    @Override    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {        System.out.println("代理之前:" + method.getName());        Object result = method.invoke(object, args);        System.out.println("代理之后:" + method.getName());        return result;    }}

    使用示例

    public class ProxyTest {    public static void main(String[] args) {        GDPeople gdPeople = new GDPeople(15, "Tom");        Human proxyInstance = (Human) ProxyFactory.getProxyInstance(gdPeople);        int age = proxyInstance.getAge();        String name = proxyInstance.getName();        System.out.println("name:" + name + "-----age:" + age);    }}

    输出结果

    运行上述代码,输出结果如下:

    name:Tom-----age:15

    总结

    通过本文的详细分析和代码示例,我们可以看到动态代理是一种强大的设计模式,能够在不修改目标类源代码的情况下,动态地增强目标类的方法行为。在实际应用中,动态代理广泛应用于日志记录、性能监控、安全性验证等场景。

    转载地址:http://chca.baihongyu.com/

    你可能感兴趣的文章
    PostgreSQL9.1 双机部署配置(主备数据同步)
    查看>>
    Qt开发——简易网络浏览器(一)
    查看>>
    Qt开发——简易成绩登记系统
    查看>>
    Postgresql中PL/pgSQL代码块的语法与使用-声明与赋值、IF语句、CASE语句、循环语句
    查看>>
    Postgresql中PL/pgSQL的游标、自定义函数、存储过程的使用
    查看>>
    SpringBoot中集成XXL-JOB分布式任务调度平台,轻量级、低侵入实现定时任务
    查看>>
    Postgresql中的表结构和数据同步/数据传输到Mysql
    查看>>
    Postgresql中自增主键序列的使用以及数据传输时提示:错误:关系“xxx_xx_xx_seq“不存在
    查看>>
    SpringBoot中集成websocket后WebSocketServer中注入mapper为空
    查看>>
    postgreSQL入门命令
    查看>>
    PostgreSQL删除数据库报"ERROR: There is 1 other session using the database."
    查看>>
    Qt开发——爱情公寓人事管理系统
    查看>>
    Qt开发——文件下载软件
    查看>>
    PostgreSQL和Oracle两种数据库有啥区别?如何选择?
    查看>>
    Qt开发——多线程网络时间服务器端
    查看>>
    Postgresql在Windows中使用pg_dump实现数据库(指定表)的导出与导入
    查看>>
    PostgreSQL在何处处理 sql查询之四
    查看>>
    postgresql基本使用
    查看>>
    PostgreSQL学习总结(10)—— PostgreSQL 数据库体系架构
    查看>>
    PostgreSQL学习总结(11)—— PostgreSQL 常用的高可用集群方案
    查看>>