动态代理学习笔记

在开发中会有这种情况 , 你有a类 , 本来是调用c 类中的方法 , 完成某个功能 , 但是c不让a调用 ,

a ---- 不能调用c的方法

在 a和c中间直接创建一个 b 代理 , c 让 b 访问 , a – 访问 b – b 访问 c

代理模式 :

代理模式是指 , 为其他对象提供一种代理 以控制对这个对象的访问 , 在某些情况下 , 一个对象不适合或者不能直接引用另一个对象 , 而代理对象可以在客户类和目标对象直接起到中介的作用 ,

换句话说 , 使用代理对象 , 是为了在不修改目标对象的基础上 , 增强主业务的逻辑 ,

使用代理模式的作用 :

  • 功能增强 : 在你原有的基础上 ,增加了额外的功能 , 新增加的功能 , 叫做功能增强
  • 控制访问 : 代理类不让你访问目标 , 例如 , 实体类中 , 不让直接访问实体类的内容 ,但是添加了get 和set方法 , 用来对内容进行修改

静态代理:

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

特点 : 实现简单 , 容易理解

实现步骤 :

  • 创建一个接口 , 定一个方法 , 表示你的厂家和商家要做的事情
  • 创建厂家类 , 实现一步骤的接口
  • 创建商家 , 就是代理 , 也要实现1步骤中的接口
  • 创建客户端类 , 调用商家的方法买

缺点:

  • 当目标类增加了 , 代理类也需要成倍的增加 , 代理类数量过多
  • 当你的接口中功能增加了 , 会影响众多的实现类 , 厂家类 , 代理类都需要修改 , 影响比较大

动态代理:

在静态代理中目标类很多的时候 , 可以使用动态代理 , 避免静态代理的缺点

优点 :

动态代理中目标类即使很多 ,

  • 代理类数量可以很少
  • 当你修改了接口中的方法时 , 不会影响代理类

动态代理简介 :

基于反射机制 :

​ 使用jdk的反射机制 , 创建对象的能力 , 创建的是代理类的对象 , 而不用你写java对象

换句话说 ,动态代理是一种创建java对象的能力 , 让你不用创建实现类 , 就能创建代理对象

在java中 , 想要创建对象 ,

  • 创建类文件 , java文件编译为class
  • 使用构造方法 , 创建类的对象

动态代理的实现分类 :

  • 动态代理分类:

    ​ 动态代理是指 : 程序在整个运行过程中根本就不存在目标类的代理类 , 目标对象的代理对象只是由代理生成工具(不是真实定义的类) 在程序运行时由JVM根据反射等机制 , 动态生成的 , 代理对象与目标对象的代理关系在程序运行的时候才确立

    JDK动态代理 :

    动态代理的实现方式常用的有两种 , 使用JDK的Proxy , 和通过CGLIB生成代理

    JDK的动态代理要求目标对象必须有实现接口, 这是java设计上的要求

    从jdk1.3以来 , java语言通过java.lang.reflect 包提供三个类支持代理模式 Proxy , Method ,和InovcationHandler

    CGLID动态代理 :

    CGLIB (Code Generation Library)是一个开源项目 , 是一个强大的 , 高性能 ,高质量的Code生成类库

    它可以在运行期间扩展java类与实现java接口 , 它广泛的呗许多AOP的框架使用 , 例如Spring AOP

    对于无接口的类, 要为其创建动态代理 , 就要使用CGLIB来实现

    CGLIB代理的方式是 : 
    	生成目标类的子类 , 而子类是增强过的 , 这个子类对象就是代理对象 , 所以使用CGLIB生成动态代理的要求就是 目标类能够被继承 , 即不能是final的类 
    

    CGLIB经常被应用在框架中 , Spring , Hibernate等 cglib代理的效率高于jdk

    项目中使用动态代理的地方不多 , 一般都是使用框架提供的功能

JDK动态代理 主要类简介:

反射包中 java.lang.reflect , 里面有三个类 , :

(1) InvocationHandler 接口 ( 中文名称叫做 : 调用处理器 )

  • 这是一个接口 , 在这个接口中只有一个方法 , invoke ()

  • invoke():表示代理对象要执行的功能代码 , 你的代理类要完成的功能就写在invoke()方法当中

    • 代理类要完成的功能 :
      • 调用目标方法: 执行目标方法的功能
      • 功能增加 : 在目标方法调用的时候 , 增加功能
  • public Object invoke(Object proxy, Method method, Object[] args)
        Object proxy : JDK创建的代理对象 , 无需赋值
    	Method method : 目标类中的方法  ,JDK提供的method对象 , 
    	Object[] args : 目标类中方法的参数
    

怎么用 : InvocationHandler 接口 :表示你的代理要干什么

  • 我们要创建一个类 , 实现这个接口
  • 重写invoke()方法 , 把原来静态代理中代理类要完成的功能 , 写在这里

(2) Method ()

这是一个类 : 确切的说 , 他就是你的目标类中的方法 ,

作用 : 通过Method可以执行某个目标类的方法 ,

  • Method.invoke();
  • 这个invoke和上边的invoke是不一样的 , 这个只是 Method类中的一个方法
method.invoke(目标对象 , 方法的参数);
通过这个方法 , 可以直接执行这个对象中的方法 , 而不需要知道方法的名称 , 

(3) Proxy : 核心的对象 , 创建代理对象 ,

方法 : newProxyInstance()

作用是 : 创建代理对象

public static Object newProxyInstance(student.getClass().getClassLoader(), student.getClass().getInterfaces(), new InvocationHandler())
    /*
    参数 : 
ClassLoader loader : 类加载器 , 负责向内存中加载对象的 , 使用反射获取对象的ClassLoader
	使用的是目标对象的类加载器
Class<?>[] interfaces : 接口 , 目标对象实现的接口 , 也是反射获取的
InvocationHandler h : 我们自己写的代理类要完成的功能

返回值 : 就是代理对象 
	
    */

动态代理实现步骤 JDK :

动态代理的实现步骤 :JDK
1.创建目标类 , SomeServiceImpl 目标类 , 给它的方法进行增强
2.创建InvocationHandler接口的实现类 , 在这个类实现给目标方法增加功能 (或者直接创建内部类也行)
3.使用JDK中类 , Proxy创建代理对象 , 实现创建对象的能力 , 使用代理对象调用目标方法
//使用jdk的Proxy创建代理对象
        //创建目标对象
        SomeService target = new SomeServiceImpl();

        //使用Proxy创建代理
        SomeService proxy = (SomeService) Proxy.newProxyInstance(target.getClass().getClassLoader(),
                target.getClass().getInterfaces(), new InvocationHandler() {
                    @Override
                    //通过代理对象执行方法时 , 会调用执行这个invoke()
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        System.out.println("执行了内部类的方法");
                        Object res = null;
                        myUtil.vlog();//增强功能
                        //执行目标类的方法 , 通过Method类实现 , method就是目标方法
                        res = method.invoke(target, args);
                        //执行的是SomeServiceImpl中的方法 , 这里的target就是SomeServiceImpl目标类
                        //SomeService target = new SomeServiceImpl();
                        //arg就是传递过来的值 , 是在下边调用的时候 , 传递的 
                        myUtil.aVoid();//增强功能
                        return res;
                    }
                });
        //proxy就是创建的代理对象 , 这里调用的是什么方法 ,
        // method.invoke(target, args);  执行的就是什么方法
        proxy.doOther();
        //通过代理执行方法 , 会调用上边的中的invoke()方法(继承的那个方法)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值