• JDK动态代理


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

    Proxy JDK动态代理 面向接口

    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
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82

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

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

    在这里插入图片描述

    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);
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
  • 相关阅读:
    Oracle Cloud Shell(甲骨文云Shell)+ FRP(反向代理)实现防火墙穿透,内网端口映,射公网
    一篇文章教你Pytest快速入门和基础讲解,一定要看
    C++:重定义:符号重定义:变量重定义
    【消息中间件】默认的RocketMQ消息消费者是如何启动的?
    计算机毕业设计ssm汽车租赁管理系统n5s69系统+程序+源码+lw+远程部署
    Git基础命令
    订单流图表与普通K线图的不同
    Oracle SQL基础
    VMWare和CentOS 7 的超级详细的安装步骤!!
    【Java】Java生成PDF工具类
  • 原文地址:https://blog.csdn.net/tomorrowAO/article/details/127972164