• JDK动态代理和CGLIB动态代理


    静态代理

    在了解动态代理之前先来学习静态代理吧
    无论是动态代理还是静态代理,本质上都是利用代理模式来实现的

    静态代理:所谓静态代理关键就在于静态,在JVM编译代码之前,代理类就已经基于目标类实现好了,这就是静态,没有利用反射机制,在程序运行时动态加载代理对象.

    如下实现一个简单的静态代理
    1.目标类接口

    /**
     * 目标类接口
     */
    public interface Animal {
        public void eat();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    2.目标类对象

    /**
     * 目标类对象
     */
    public class Dog implements Animal{
        private String name;
        public Dog(String name){
            this.name = name;
        }
        @Override
        public void eat() {
            System.out.println(name+"is eating");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    3.代理类对象

    /**
     * 代理对象
     */
    public class Proxy implements Animal{
        //目标对象
        private Dog target;
        public Proxy(Dog target){
            this.target = target;
        }
        @Override
        public void eat() {
            System.out.println("增强方法");
            target.eat();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    由上可见代理对象proxy的在程序运行之前就已经编译好了

    动态代理相较于静态代理的优势

    详细阅读下面这篇博客,讲的非常清除

    https://www.cnblogs.com/fudashi/p/7117365.html

    动态代理

    代理类在程序运行过程中动态创建的

    那么JDK动态代理和Cglib动态代理又有什么区别呢?

    首先JDK动态代理,代理对象只能代理实现了接口的目标对象,本质上是
    通过调用反射,获取接口的结构信息,然后接口结构信息获取到目标方法
    然后对目标方法进行了重写,重写中是调用了Invocationhandler对象的invoke方法,说着很绕,看下面这篇博客
    https://zhuanlan.zhihu.com/p/54733692
    JDK动态代理的简单实现
    1.目标接口

    /**
     * 声明接口
     */
    public interface Person {
        public void say();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    2.目标对象

    public class Student implements Person{
        private String name;
        public Student(String name){
            this.name = name;
        }
        public void say(){
            System.out.println("hello i am"+name);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    3.InvocationHandler接口的实现类,实现invoke()增强方法

    /**
     * jdk动态代理,实现Invocationhnadler接口
     */
    public class JdkinvocationHandler<Objeact> implements InvocationHandler {
        private Objeact target;//目标对象
    
        public JdkinvocationHandler(Objeact target) {
            this.target = target;
        }
        //method是目标方法,proxy是代理对象,target是目标对象
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            System.out.println("bofore");
            Object res = method.invoke(target, args);
            return res;
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    而Cglib动态代理,代理对象代理的目标对象可以不用实现接口,本质上是实现了一个目标类的增强子类,但是使用Cglib动态代理需要引入依赖

    Cglib动态代理的简单实现
    1.目标类

    public class Teacher {
        private String name;
        public Teacher(String name){
            this.name = name;
        }
        public void say(){
            System.out.println("hello i am"+name);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    2.MethodInterceptor接口的实现类,实现intercept()增强方法

    /***
     * cglib动态代理,目标类不用实现接口
     */
    public class Cglib implements MethodInterceptor {
        private Object target;
        public Cglib(Object target){
            this.target = target;
        }
        /*
        * 第一个参数时代理对象
        * 第二个参数是目标方法
        * 第三个参数是目标方法的参数
        * 第四个参数是目标方法的代理
        * */
        @Override
        public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
            System.out.println("最强方法前");
            Object res = methodProxy.invoke(target, args);
            System.out.println("最强方法后");
            return res;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    引用场景

    1.Spring的AOP利用了Cglib动态代理
    2.Mybatis的获取mapper实力对象利用了JDK动态代理

  • 相关阅读:
    第七章 防火墙
    神经网络训练不起来,怎么办?
    【IoT毕设.上】STM32+机智云AIoT+实验室安全监控系统
    macOS下如何使用Flask进行开发
    vue 滚动缩放反转图片功能
    图片隐写,盲水印,加密logo
    JS中的括号和点号
    USB学习(1):USB基础之接口类型、协议标准、引脚分布、架构、时序和数据格式
    java spring cloud 企业工程管理系统源码+二次开发+定制化服务
    h5修改钉钉双标题栏问题
  • 原文地址:https://blog.csdn.net/TheWayForDream/article/details/126001321