【JavaWeb】JDK动态代理 — 代理模式;静态代理;动态代理;JDK动态代理的实现及实现原理分析

需要掌握的程度:

  1. 什么是JDK动态代理 ?

使用jdk的反射机制,创建对象的能力(创建的是代理类的对象),而不用创建类文件,不用写java文件。

  • 动态:在程序执行时,调用jdk提供的方法才能创建代理类的对象。
  • jdk动态代理,必须有接口,目标类必须实现接口, 没有接口时,需要使用cglib动态代理。

  • 知道动态代理能做什么?

可以在不改变原来目标方法功能的前提下, 可以在代理中增强自己的功能代码。

代理模式:

1.代理:代购, 中介,换ip,商家等等。

  • 比如有一家美国的大学, 可以对全世界招生。
  • 留学中介(代理): 帮助这家美国的学校招生, 中介是学校的代理, 中介是代替学校完成招生功能。

为什么要找中介 ?

  • 中介是专业的, 方便。
  • 家长现在不能自己去找学校。 家长没有能力访问学校。 或者美国学校不接收个人来访。

买东西都是商家卖, 商家是某个商品的代理, 你个人买东西, 肯定不会让你接触到厂家的。

  1. 在开发中也会有这样的情况:

  2. a类, 本来要调用c类的方法, 完成某个功能,但是c不让a调用。

解决方案:

  • 在 a 和 c 直接 创建一个 b 代理, c 让 b访问。

a — 访问b — 访问c

3.使用代理模式的作用

  • 功能增强: 在你原有的功能上,增加了额外的功能。
  • 控制访问: 代理类不让你访问目标,例如商家不让用户访问厂家。

静态代理 :

  • 代理类是自己手动实现的,自己创建一个java类,表示代理类;同时你所要代理的目标类是确定的。

优点:实现简单;容易理解。

缺点:当你的项目中,目标类和代理类很多的时候:

1)当目标类增加了, 代理类可能也需要成倍的增加,代理类数量过多。

2)当你的接口中功能增加了, 或者修改了,会影响众多的实现类,厂家类,代理类都需要修改,影响比较多。

动态代理:

  • 在程序执行过程中,使用jdk的反射机制,创建代理类对象, 并动态的指定要代理目标类;换句话说: 动态代理是一种创建java对象的能力,让你不用创建代理类,就能创建代理类对象。

优点:

1)代理类数量可以很少。

2)当你修改了接口中的方法时,不会影响代理类。

动态代理的实现:

  • jdk 动态代理(理解):使用 java 反射包中的类和接口(InvocationHandler , Method, Proxy)实现动态代理的功能。

  • cglib动态代理(了解): cglib是第三方的工具库,cglib的原理是继承, cglib通过继承目标类,创建它的子类,在子类中重写父类中同名的方法, 实现功能的修改。

由于cglib是继承,重写方法,所以要求目标类不能是final的, 方法也不能是final的。

cglib的要求目标类比较宽松, 只要能继承就可以了。cglib在很多的框架中使用,比如 mybatis ,spring框架中都有使用。

jdk 动态代理实现步骤:

1、创建接口,定义目标类要完成的功能:

//目标接口
public interface UsbSell {
    float sell(int amount);
}

2、创建目标类实现接口:

//目标类
public class UsbKingFactory implements UsbSell {
    @Override
    //目标方法
    public float sell(int amount) {
        //厂家卖85.6元
        return 85.6f;
    }
}

3、创建InvocationHandler接口的实现类,在invoke方法中完成代理类的功能:

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

//必须实现InvocationHandler接口,完成代理类要做的功能(1.调用目标方法,2.功能增强)
public class MySellHandler implements InvocationHandler {
    private Object target = null;

    //动态代理:目标对象是活动的,不是固定的,需要传入进来,传入是谁,就给谁创建代理。
    public MySellHandler(Object target) {
        //给目标对象赋值
        this.target = target;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //储存方法执行结果
        Object res  = null;

        //执行目标方法
        res =  method.invoke(target,args);

        //商家需要加价(功能增强)
        if( res != null ){
            Float price = (Float)res;
            price = price + 25;
            res = price;
        }

        //再送你一张优惠券(功能增强)
        System.out.println("谢谢惠顾,送您一张优惠券,亲!");

        //增加的价格
        return res;
    }
}

4、使用Proxy类的静态方法,创建代理对象。 并把返回值转为接口类型:

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;

public class MainShop {
    public static void main(String[] args) {
        //1. 创建目标对象
        UsbSell factory = new UsbKingFactory();

        //2.创建InvocationHandler对象
        InvocationHandler handler = new MySellHandler(factory);

        //3.创建代理对象
        UsbSell proxy = (UsbSell) Proxy.newProxyInstance(factory.getClass().getClassLoader(),
                factory.getClass().getInterfaces(),
                handler);

        //4.通过代理执行方法
        float price = proxy.sell(1);
        System.out.println("通过动态代理对象,调用方法获得的结果:"+price);
    }
}

JDK动态代理执行流程 :

Original: https://www.cnblogs.com/Burning-youth/p/16165448.html
Author: 猿头猿脑的王狗蛋
Title: 【JavaWeb】JDK动态代理 — 代理模式;静态代理;动态代理;JDK动态代理的实现及实现原理分析

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/586406/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • Spring Cloud Alibaba 环境搭建

    可以手动从一个 Maven 项目进行搭建,后期也可以利用 Idea 工具直接从阿里云官网进行快捷搭建,网址为Aliyun Java Initializr,类似于 SpringBoo…

    Java 2023年6月5日
    093
  • 7.Hystrix缓存特性及请求特性

    Hystrix请求缓存 Hystrix支持将请求结果进行本地缓存 通过实现getCacheKey方法来判断是否取出缓存 请求缓存要求请求必须在同一个上下文 可以用过RequestC…

    Java 2023年6月8日
    054
  • Java 方法重写

    重写需要有继承关系,子类重写父类的方法! 重写的条件 1.方法名必须相同2.参数列表必须相同3.修饰符:范围可以扩大 :public>Protected>Default…

    Java 2023年6月9日
    038
  • IOC常用的创建对象方式

    1、User.java public class User { private String name; public User() { System.out.println(&q…

    Java 2023年6月15日
    041
  • 构建系统概念

    什么是构建系统 构建系统的 第一要务 是将系统源代码编译成可执行的文件。 在这基础之上,它允许通过机器自动创建 build,如提交代码到 GitHub 后自动触发构建。 javac…

    Java 2023年6月5日
    068
  • [转载]Redis 持久化之RDB和AOF

    在正式数据(当然是非生产环境啦)练习以下操作时,一定一定一定记得备份dump.rdb文件。我给自己的服务器添加了aof持久化配置,重启后,发现aof文件为空,就想把rdb文件恢复到…

    Java 2023年6月6日
    070
  • 设计模式—六大设计原则

    六大设计原则 单一职责原则 我们分别看两个案例,一个是遵守单一职责原则,另一个是违背。 违背的案例 public class Computer { void calc() { Sy…

    Java 2023年6月7日
    069
  • 什么是哈夫曼树

    写在前面 之前讲的链表,栈,队列等都是线性存储结构,都是 一对一的关系。而树是具有 一对多关系的数据结构。比如我们经常说的湖北省武汉市,湖南长沙的一个类图,就类似于一颗倒转的树。 …

    Java 2023年6月5日
    097
  • 草图?不管黑猫白猫,能把你的设计理念讲清楚才行

    我在日常工作中,经常要参加一些技术活动,或被拉去参加一些需求会或运营会,时间比较分散。 上周在参加一个代码评审时,发现程序上该复用的没有复用,却写了两份逻辑几乎相同的代码。另外,还…

    Java 2023年6月15日
    082
  • 已数组作为参考过滤数组数据

    this.purchaseDetailList = this.purchaseDetailList.filter((item) => !this.addDataList.so…

    Java 2023年6月5日
    077
  • Java相关面试题

    =与== = 属于逻辑运算符,将右侧的值赋给左侧的变量名称 ==数据关系运算符,判断左右两边的值是否相等,结果为boolean类型 &与&& &是逻…

    Java 2023年5月29日
    087
  • Nginx报504 gateway timeout错误的解决方法

    一、今天登录我的网站,突然发现报了下面的一个错误: 我的第一反应是:超时了应该是Nginx代理没有设置超时时间,默认的超时时间估计太小了,然后就按照正常的方式用Xshell连接服务…

    Java 2023年6月13日
    063
  • Skywalking-04:扩展Metric监控信息

    扩展 Metric 监控信息 官方文档 Source and Scope extension for new metrics 案例: JVM Thread 增加 Metrics 修…

    Java 2023年6月5日
    099
  • Spring表达式语言

    初次遇见@Value注解的时候,总以为它的功能非常生硬,只能注入硬编码的字面量值。后来随着学习的深入,渐渐发现@Value注解也能注入属性文件的值,非常好用。让人格外惊喜的是,@V…

    Java 2023年6月5日
    076
  • MSSQL·FOR XML PATH语法转义尖括号解决方案

    阅文时长 | 0.14分钟字数统计 | 225.6字符主要内容 | 1、引言&背景 2、示例及解决方案 3、声明与参考资料『MSSQL·FOR XML PATH语法转义尖括…

    Java 2023年6月5日
    073
  • 索引有什么分类?

    索引有什么分类? – 1、主键索引:名为primary的唯一非空索引,不允许有空值。 – 2、唯一索引:索引列中的值必须是唯一的,但是允许为空值。唯一索引和…

    Java 2023年6月5日
    066
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球