JDK动态代理笔记,学习框架必备知识,学习框架之前先学一下这个

目录

原理

暂时的掌握程度

动态代理模式的作用

静态代理

动态代理

动态代理的分类

Method类的复习(其实是预习)

三个类的介绍

实现动态代理的步骤


  1. 原理

    1. 基于反射机制

    2. a想要访问c,但是a没有访问c的权限;这是可在a、c之间创建一个可以被a访问且能访问c的b;a就可以通过访问b,让b去访问c,间接访问c;并且还可以在b上实现更多的业务

  2. 暂时的掌握程度

    1. 先做了解,之后学mybatis和spring再学习怎么用

    2. 知道是什么动态代理?

    3. 知道动态代理能做什么?

  3. 动态代理模式的作用

    1. 功能增强:在原有基础上增加新功能;除了接口的实现功能外,其他功能都是增强功能

    2. 控制访问:代理类可不让你访问目标

  4. 静态代理

    1. 需要手动实现,创建一个Java类来作为代理类

    2. 优缺点:

      1. 优点:实现简单、容易理解

      2. 缺点:代理类过多、难修改(需要一个个修改)

    3. 例子

      1. 需求:模拟一个用户购买某品牌U盘

        1. 用户是客户端类;商家是代理类,代理某品牌的U盘;厂家是目标类

        2. 商家和厂家都是卖U盘的,他们完成的功能是一致的,都是卖U盘

      2. 实现步骤:

        1. 创建一个接口,定义卖U盘的方法,表示你的厂家和商家做的事情

        2. 创建厂家类,实现步骤1的接口

        3. 创建商家类(代理类),同样要实现步骤1的接口

        4. 创建客户端类,调用商家的方法买U盘

  5. 动态代理

    1. 什么是动态代理:

      1. 使用jdk的反射机制,创建对象的能力,创建的是代理类的对象。不需要我们创建类文件

      2. 动态:在程序执行时,调用jdk提供的方法才能创建代理类的对象

    2. 优点:

      1. 避免了静态代理的缺点,代理类数量可以很少,修改接口中的方法时不会影响代理类

    3. 实现:

      1. 在程序执行过程中,使用jdk的反射机制,创建代理类对象,并动态的指定要代理的目标类

      2. 简而言之:不用创建代理类就能够创建代理对象(接口--->对象)

      3. 注意:学框架再学实现

  6. 动态代理的分类

    1. jdk动态代理(理解)

      1. 使用Java反射包中的类和接口实现动态代理的功能

      2. Java反射包的三个类:InvocationHandler、Method、Proxy

    2. ogLib动态代理(了解)

      1. ogLib是第三方工具库,使用该工具库来创建代理对象

      2. ogLib的原理是继承和重写方法。通过继承目标类创建它的子类,在子类中重写父类中同名的方法,实现功能的修改

      3. 因为ogLib的机制是继承和重写方法,所以要求目标类和方法不能是final的(要求宽松,能继承即可)

      4. ogLib在很多框架中使用

  7. Method类的复习(其实是预习)

    1. invoke()方法

      1. 是Method类的一个方法,表示执行方法的调用(用来调用方法)

      2. 参数:参数1:Object,表示这个对象要执行的方法; 参数2:Object...,方法执行时的参数值

      3. 返回值:Object,方法执行的返回值

    2. 代码展示

      1. 纯净版

public static void main(String[] args) throws Exception {
    HelloService target = new HelloServiceImpl();
    Method method = HelloService.class.getMethod("sayHello", String.class);
    Object ret = method.invoke(target, "李四");
}
  1. 有注释笔记版

// 使用反射机制执行sayHello方法。核心Method类中的方法
public static void main(String[] args) throws Exception {
    // 创建一个需要执行方法的对象
    HelloService target = new HelloServiceImpl();
    // 获取sayHello名称对应的Method类对象
        // 参数1:需要获取的对象的名称(方法名称);   参数2:该方法参数的数据类型
    Method method = HelloService.class.getMethod("sayHello", String.class);
    // 通过Method对象执行target的sayHello方法
        /*
        invoke是Method类的一个方法,表示执行方法的调用(用来调用方法)
        参数:参数1:Object,表示要执行的方法的对象; 参数2:Object...,方法执行时的参数值
        返回值:Object,方法执行的返回值
         */
        // 需要执行sayHello方法的对象是target,方法的参数是“李四”(执行target的sayHello方法,参数是“李四”)
    Object ret = method.invoke(target, "李四");
}
  1. 三个类的介绍

    1. Java反射包(java.lang.reflect)的三个类:InvocationHandler、Method、Proxy

    2. InvocationHandler接口(调用处理器)

      1. InvocationHandler接口用来表示代理要干的事情

      2. invoke()方法(该接口只有一个方法)

        1. invoke()方法表示代理对象要执行的功能代码。代理类要完成的功能写在invoke()方法里面。

        2. 代理类完成的功能:

          1. 调用目标方法,执行目标方法的功能

          2. 功能增强,在目标方法调用时,增加功能

        3. 方法原型:public Object invoke(Object proxt, Method method, Object[] args){...}

          1. 参数分析:(第一个参数不需要赋值,传递后两个参数即可)

            1. Object proxt:jdk创建的代理对象,无需赋值(这个参数不需要我们赋值)

            2. Method method:目标类中的方法,jdk提供method对象

            3. Object[] args:目标类中方法的参数

        4. 使用方式:

          1. 创建InvocationHandler接口的实现类

          2. 重写invoke()方法,把要实现的功能写在该方法里

    3. Method类

      1. Method类用来表示目标类中的方法,可用于调用invoke方法来执行方法

      2. 作用:通过Method类可以执行某个目标类的方法Method.invoke(目标对象, 方法参数)

    4. Proxy类

      1. Proxy类用来创建代理对象,Proxy类对象是核心的对象。常规创建对象是“new 类的构造方法”,现使用Proxy类的方法来代替new

      2. newProxyInstance()静态方法

        1. 作用:创建代理对象

        2. 方法原型:public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)

          1. ClassLoader loader:类加载器,负责向内存中加载对象,使用反射获取对象的ClassLoader

          2. Class<?>[] interfaces:通过反射获取的目标对象的类所实现的接口

          3. InvocationHandler h:代理类要完成的功能,我们自己写(就是InvocationHandler接口的实现类,重写的invoke方法包含了要实现的功能)

          4. 返回值:代理对象

  2. 实现动态代理的步骤

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

    2. 创建目标类实现接口

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

      1. 调用目标方法

      2. 增强功能

    4. 使用Proxy类的静态方法创建代理对象,并把代理对象转为接口类型

    5. 代码展示

      1. 创建接口

package com.bjpowenode.service;

// 目标接口
public interface UsbSell {
    //
    float sell(int amount);
}
  1. 创建目标类实现接口

package com.bjpowenode.factory;

import com.bjpowenode.service.UsbSell;

public class UsbKingFactory implements UsbSell {
    @Override
    public float sell(int amount) {
        System.out.println("目标类中,执行sell目标方法");
        return 85.0f;
    }
}
  1. 创建InvocationHandler接口的实现类

package com.bjpowenode.handler;

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

// 实现InvocationHandler接口,完成代理类要做的功能(调用目标方法、功能增强)
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;
    }
}
  1. 创建代理对象,并执行功能

package com.bjpowenode;

import com.bjpowenode.factory.UsbKingFactory;
import com.bjpowenode.handler.MySellHandler;
import com.bjpowenode.service.UsbSell;

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

public class MsinShop {

    public static void main(String[] args) {
        // 使用Proxy类的静态方法创建代理对象,并把代理对象转为接口类型

        // 1、创建目标对象
        UsbSell factory = new UsbKingFactory();
        // 2、创建InvocationHandler对象
        InvocationHandler handler = new MySellHandler(factory);
        // 3、创建代理对象。
        // getClass()方法是获取对象的类,     getInterfaces()方法是获取类所实现的接口
        // getClassLoader()方法是获取这个类的加载器(类加载器负责读取 Java 字节代码,并转换成 java.lang.Class类的一个实例。)
        UsbSell proxy = (UsbSell) Proxy.newProxyInstance(factory.getClass().getClassLoader(),
                factory.getClass().getInterfaces(),
                handler);
        // 4、通过代理执行方法
        float price = proxy.sell(1);

        System.out.println("通过动态代理对象调用方法:" + price);
    }
}
  1. 注意

    1. jdk动态代理,必须有接口,目标类型实现接口,没有接口时,需要使用cglib动态代理

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值