JDK动态代理

news/2024/7/6 6:31:05 标签: java, 代理模式, 开发语言

可以针对一些不特定的类或者一些不特定的方法进行代理 可以在程序运行时动态变化代理规则
代理类在程序运行时才创建代理模式成为动态代理
代理类并不是在Java代码中定义好的 而是在程序运行时根据在Java代码中指示动态生成的

Proxy JDK动态代理 面向接口

java">import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;


public class Test1 {
    public static void main(String[] args) {
        Dinner dinner = new Student("张三");
        //通过动态代理获取一个代理对象 在代理对象中 对某个方法进行增强
        //ClassLoader loader 被代理的对象的类加载器
        ClassLoader classLoader = dinner.getClass().getClassLoader();
        //Class<?>[] interfaces 被代理对象所实现的所有接口
        Class[] interfaces =dinner.getClass().getInterfaces();
        //InvocationHandler h 执行处理器对象 专门用于定义增强的规则
        InvocationHandler handler = new InvocationHandler(){
            //invoke 当我们让代理对象调用任何方法时 都会触发invoke方法的执行
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

                //Object proxy 代理对象
                //Method method 被代理的方法
                //Object[] args 被代理方法运行时实参
                Object res = null;
                if(method.getName().equals("eat")){
                    System.out.println("饭前洗手");
                //让原有的eat方法去运行
                    res = method.invoke(dinner,args);
                    System.out.println("饭后刷碗");
                }else{
                    //如果是其他方法 正常执行
                    res = method.invoke(dinner,args);
                }
                return null;
            }
        };

        Dinner dinnerProxy = (Dinner)Proxy.newProxyInstance(classLoader,interfaces,handler);
        //dinnerProxy.eat("包子");
        dinnerProxy.eat("包子");

    }
}

interface Dinner {
    void eat(String foodName);
    void drink();
}

class Person implements Dinner{
    private String name;

    public Person(String name) {
        this.name = name;
    }

    @Override
    public void eat(String foodName) {
        System.out.println(name + "正在吃" + foodName);
    }

    @Override
    public void drink() {

    }
}

class Student implements Dinner{
    private String name;

    public Student(String name) {
        this.name = name;
    }

    @Override
    public void eat(String foodName) {
        System.out.println(name + "正在食堂吃" + foodName);
    }

    @Override
    public void drink() {
        System.out.println(name + "正在喝可乐");
    }
}

1.在不修改原有代码的 或没有办法修改原有代码的情况下
增强对象功能 使用代理对象代替原来的对象完成功能达到拓展功能的目的
2.JDK Proxy动态代理面向接口的动态代理 一定要有接口和实现类的存在
代理对象增强的是实现类 在实现接口方法重写的方法
代理对象只能增强接口中定义的的方法 类中其他和接口无关的方法无法增强
代理对象只能读取接口中方法上的注解 不能读取到实现类方法的注解

cglib 第三方动态代理 面向父类

在这里插入图片描述

java">import org.junit.Test;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;

public class Test1 {
    @Test
    public void testCglib(){
        Person person = new Person();
        //获取一个Person代理对象
        //1.获取一个Enhancer对象
        Enhancer enhancer = new Enhancer();
        //2.设置父类的字节码
        enhancer.setSuperclass(person.getClass());
        //3.获取MethodIntercepter对象 用于定义增强规则
        MethodInterceptor methodInterceptor = new MethodInterceptor() {
            @Override
            public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
                /*
                * Object o 生成以后的代理对象 personProxy
                * Method method 父类中原本要执行的方法 Person >>> eat()
                * Object[] objects 方法在调用时传入的实参数组
                * MethodProxy methodProxy 子类中重写父类的方法 personProxy >>> eat()
                */
                Object res = null;
                if (method.getName().equals("eat")){
                    //如果是eat方法 增强并运行
                    System.out.println("饭前洗手");
                    methodProxy.invokeSuper(o,objects);
                    System.out.println("饭后刷碗");
                }else{
                    //如果是其他方法 不增强运行
                    methodProxy.invokeSuper(o,objects);//子类对象方法执行 默认调用父类对应被重写的方法
                }
                return res;
            }
        };
        //4.设置回调方法
        enhancer.setCallback(methodInterceptor);
        //5.获得methodInterceptor
        Person personProxy = (Person) enhancer.create();
        //6.使用代理对象完成功能
        personProxy.eat("包子");
    }

class Person {
   private String name;

    public Person() {

    }

   public void eat(String foodName) {
      System.out.println("张三" + "正在吃" + foodName);
        }
    }
}

http://www.niftyadmin.cn/n/10608.html

相关文章

【华为OD机试真题 python】 城市聚集度【2022 Q4 | 200分】

■ 题目描述 【城市聚集度】 一张地图上有n个城市,城市和城市之间有且只有一条道路相连:要么直接相连,要么通过其它城市中转相连(可中转一次或多次)。城市与城市之间的道路都不会成环。 当切断通往某个城市 i 的所有道路后,地图上将分为多个连通的城市群,设该城市i的…

IDEA Windows下SPARK连接Hive

IDEA Windows下SPARK连接Hive 文章目录IDEA Windows下SPARK连接Hive一、本地Windows环境配置二、IDEA项目配置1. POM配置2. 资源文件配置3. 测试验证一、本地Windows环境配置 本地构建HADOOP客户端 将大数据平台的HAODOP环境打包拿到本地环境来&#xff1a; #压缩整个HADOOP…

ggplot2 | 世界杯赛程的可视化就交给我吧!~

11. 写在前面 昨天卡塔尔&#x1f1f6;&#x1f1e6;输了比赛真是让人大跌眼镜啊&#x1f631;&#xff0c;打破了世界杯东道主必胜的神律&#xff0c;也不知道王子们是怎么想的。&#x1f923; 今天是英格兰&#x1f3f4;&#xe0067;&#xe0062;&#xe0065;&#xe006e…

股票买卖Ⅴ

题目描述 给定一个长度为 NNN 的数组&#xff0c;数组中的第 iii 个数字表示一个给定股票在第 iii 天的价格。 设计一个算法计算出最大利润。在满足以下约束条件下&#xff0c;你可以尽可能地完成更多的交易&#xff08;多次买卖一支股票&#xff09;: 你不能同时参与多笔交…

【改进灰狼优化算法】基于协调探索和开发能力的改进灰狼优化算法求解单目标优化问题(Matlab代码实现)

&#x1f468;‍&#x1f393;个人主页&#xff1a;研学社的博客 &#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜…

高速串行信号串接电容放在发送端还是接收端

在设计一些高速的串行信号&#xff0c;比如PCIE&#xff0c;STATA&#xff0c;USB3.0等&#xff0c;在差分信号线上面常常都会串接一个电容 这个电容主要有如下几个方面的作用&#xff1a; 1.滤除信号的直流分量&#xff0c;使信号关于0电平对称&#xff1b; 因为很多高速信号…

周年更名,元宇宙产业委再上新台阶

今天&#xff0c;2022年11月10日&#xff0c;全球元宇宙大会在鹏城隆重举行&#xff0c;这个日子也是中国移动通信联合会元宇宙产业工作委员会成立一周年的日子。会上&#xff0c;我们宣布了这个更名消息&#xff0c;这也是元宇宙产业工作委员会迈上一个新台阶的标志。有20多家…

接口自动化测试

接口自动化测试1.基础知识1.接口测试原理2.接口测试点及用例设计方法3.接口测试返回值的处理4.接口测试要点5.常见HTTP状态码6.HTTP基础知识7.接口自动化测试工具2.抓包工具1.chrom抓包2.Fiddle抓包&#xff08;PC端&#xff0c;手机端&#xff09;1.原理2.下载安装3. 认识界面…