Java动态代理的示例详解

 更新时间:2022年02月23日 17:17:43   作者:温故知新之java  
动态代理指的是,代理类和目标类的关系在程序运行的时候确定的,客户通过代理类来调用目标对象的方法,是在程序运行时根据需要动态的创建目标类的代理对象。本文将通过案例详细讲解一下动态代理,需要的可以参考一下

定义

动态代理指的是,代理类和目标类的关系在程序运行的时候确定的,客户通过代理类来调用目标对象的方法,是在程序运行时根据需要动态的创建目标类的代理对象。

分类

jdk动态代理

cglib动态代理

案例

需求

苹果公司通过苹果代理商来卖手机

方案一:jdk动态代理

定义抽象接口

/**
 * 售卖手机的接口(代理模式——抽象角色)
 * @author:liyajie
 * @createTime:2022/2/22 14:42
 * @version:1.0
 */
public interface IPhone {

    /**
     * 出售手机
     * @author: liyajie
     * @date: 2022/2/22 14:44
     * @param
     * @return void
     * @exception:
     * @update:
     * @updatePerson:
     **/
    void sellPhone();
}

定义目标类实现接口,重写接口方法

/**
 * 苹果公司(代理模式——目标角色)
 * @author:liyajie
 * @createTime:2022/2/22 14:46
 * @version:1.0
 */
public class TargetPhone implements IPhone {
    @Override
    public void sellPhone() {
        System.out.println("苹果公司正在出售手机");
    }
}

定义代理类

/**
 * 代理商(代理模式——代理角色)
 * @author:liyajie
 * @createTime:2022/2/22 14:50
 * @version:1.0
 */
public class ProxyPhone {

    private Object target;

    public ProxyPhone(Object target){
        this.target = target;
    }

    public Object getProxyInstance() {
        return Proxy.newProxyInstance(target.getClass().getClassLoader(),
                target.getClass().getInterfaces(),
                new InvocationHandler() {
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        System.out.println("JDK动态代理开始之前,添加业务逻辑XXX");
                        //使用反射机制来调用目标对象的方法:解决了问题二
                        Object invoke = method.invoke(target, args);
                        System.out.println("JDK动态代理结束之后,添加业务逻辑XXX");
                        return invoke;
                    }
                });
    }
}

定义测试类

/**
 * 测试类
 * @author:liyajie
 * @createTime:2022/2/23 15:15
 * @version:1.0
 */
public class Test {
    public static void main(String[] args) {
        // 创建目标类
        TargetPhone targetPhone = new TargetPhone();
        // 创建代理类
        IPhone iPhone = (IPhone) new ProxyPhone(targetPhone).getProxyInstance();
        System.out.println(iPhone.getClass());
        // 通过代理类调用目标方法
        iPhone.sellPhone();
    }
}

查看测试结果

方案二:cglib动态代理

定义目标类

/**
 * 苹果公司(代理模式——目标角色)
 * @author:liyajie
 * @createTime:2022/2/22 14:46
 * @version:1.0
 */
public class TargetPhone {

    public void sellPhone() {
        System.out.println("苹果公司正在出售手机");
    }
}

定义代理工厂,用来获取代理类

/**
 * 代理工厂
 * @author:liyajie
 * @createTime:2022/2/23 15:32
 * @version:1.0
 */
public class ProxyFactory implements MethodInterceptor {

    private Object target;

    public ProxyFactory(Object target){
        this.target = target;
    }

    public Object getProxyInstance(){
        // 创建一个工具类
        Enhancer enhancer = new Enhancer();
        // 设置父类
        enhancer.setSuperclass(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("cglib动态代理开始之前,添加业务逻辑xxxx");
        Object invoke = method.invoke(target, objects);
        System.out.println("cglib动态代理之后,添加业务逻辑");
        return invoke;
    }
}

定义测试类

/**
 * 测试类
 * @author:liyajie
 * @createTime:2022/2/23 15:44
 * @version:1.0
 */
public class Test {
    public static void main(String[] args) {
        // 创建目标对象
        TargetPhone targetPhone = new TargetPhone();
        // 获取代理对象
        TargetPhone proxyInstance = (TargetPhone)new ProxyFactory(targetPhone).getProxyInstance();
        // 通过代理对象调用具体的方法
        proxyInstance.sellPhone();
    }
}

查看测试结果

分析

首先可以看到不管是jdk动态代理,还是cglib动态代理,实现的效果和静态代理是一模一样的,都实现了功能的扩展。但是两种动态代理还是有些不同的,其中jdk动态代理需要目标对象实现接口,但是cglib动态代理不需要,因为他是在内存中构建一个子类对象,从而实现对目标对象的功能扩展。

总结

通过案例,我们了解了代理模式的几种实现方式,下面我们总结下该模式:

优势:

  • 代理模式在客户端和目标对象之间起到了一个中介和保护的作用
  • 代理对象可以对目标对象进行功能的扩展和业务的扩展,增强目标对象
  • 代理模式可以将客户端和目标对象分离,在一定程度上降低了系统的耦合度

劣势:

  • 请求需要经过代理对象,会导致处理速度变慢
  • 因为会有大量的代理对象产生,会增加系统的复杂度

到此这篇关于Java动态代理的示例详解的文章就介绍到这了,更多相关Java 动态代理内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Java操作MongoDB数据库的示例代码

    Java操作MongoDB数据库的示例代码

    这篇文章主要介绍了Java操作MongoDB的示例代码,帮助大家更好的理解和学习使用Java,感兴趣的朋友可以了解下
    2021-04-04
  • Java多线程的临界资源问题解决方案

    Java多线程的临界资源问题解决方案

    这篇文章主要介绍了Java多线程的临界资源问题解决方案,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-02-02
  • 关于Mybatis插入对象时空值的处理

    关于Mybatis插入对象时空值的处理

    这篇文章主要介绍了关于Mybatis插入对象时空值的处理方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-06-06
  • SpringBoot实现评论回复功能(数据库设计)

    SpringBoot实现评论回复功能(数据库设计)

    这篇文章主要介绍了SpringBoot实现评论回复功能(数据库设计),本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-04-04
  • Mybatis之@ResultMap,@Results,@Result注解的使用

    Mybatis之@ResultMap,@Results,@Result注解的使用

    这篇文章主要介绍了Mybatis之@ResultMap,@Results,@Result注解的使用,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-12-12
  • 基于java socket实现 聊天小程序

    基于java socket实现 聊天小程序

    这篇文章主要介绍了基于java socket实现 聊天小程序,代码分为服务器和客户端,本文通过实例代码给大家介绍的非常详细,具有一定的参考借鉴价值,需要的朋友可以参考下
    2019-12-12
  • 手把手带你分析SpringBoot自动装配完成了Ribbon哪些核心操作

    手把手带你分析SpringBoot自动装配完成了Ribbon哪些核心操作

    这篇文章主要介绍了详解Spring Boot自动装配Ribbon哪些核心操作的哪些操作,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-08-08
  • Java虚拟机启动过程探索

    Java虚拟机启动过程探索

    当我们在编写Java应用的时候,很少会注意Java程序是如何被运行的,如何被操作系统管理和调度的,带着好奇心,探索一下Java虚拟机启动过程
    2022-05-05
  • springboot之使用logback日志框架的图文教程

    springboot之使用logback日志框架的图文教程

    这篇文章主要介绍了springboot之使用logback日志框架的图文教程,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-06-06
  • Java中synchronized正确使用方法解析

    Java中synchronized正确使用方法解析

    这篇文章主要介绍了Java中syncronized正确使用方法解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-09-09

最新评论