当前位置: 首页 > article >正文

Spring底层原理学习笔记--第十一讲--(aop之proxy增强-jdk及aop之proxy增强-cglib)

AOP实现之proxy

  • 1.jdk动态代理实现及要点

  • 2.cglib代理实现及要点

    invoke与invokeSuper区别

jdk动态代理实现及要点

package com.lucifer.itheima.a12;

import java.lang.reflect.Proxy;

public class JdkProxyDemo {

    interface Foo{
        void foo();
    }

    //该类可以设置成final类型 
    //jdk中的代理跟目标是平级的兄弟关系,他们都实现了共同的接口
    static class Target implements Foo{
        public void foo(){
            System.out.println("target foo");
        }
    }

    //jdk只能对接口代理
    //cglib 没有限制,可以对接口代理,如果没有接口的话也可以
    public static void main(String[] param) {
//        ClassLoader loader = JdkProxyDemo.class.getClassLoader();  // 用来加载在运行期间动态生成的字节码
//        //ClassLoader的作用:
//        // 代理类跟普通类有一个差别,普通类是先写java源代码,java源代码编译成java字节码,最后经过类加载然后可以使用
//        // 而代理类没有源码,它是在运行期间,直接生成代理类的字节码,生成后的字节码也要被加载后才能运行,谁来做这个操作呢,由我们的Classloader来做这个操作
//        //所以类加载器主要是用于加载代理类内部生成的字节码
//
//        Foo proxy = (Foo)Proxy.newProxyInstance(loader, new Class[] { Foo.class }, (p, method, args) -> {
//            System.out.println("before...");
//            return null;
//        });
//
//        //参数二
//        // 将来要生成的代理,要实现的是哪个接口
//        // 参数三是干什么的,大家想代理类创建出来了,它也实现了我们的接口,它要实现接口中的抽象方法,必须规定这些方法的行为,那谁来把这些行为进行封装呢,就是第三个参数来做的
//
//        //总结:参数1: 用来加载在运行期间动态生成的字节码
//        //参数2:将来要实现的接口
//        //参数3:代理类调用任何代理方法时,要执行的一些行为
//
//
//        //输出结果为
        before...
//        proxy.foo();


        //目标对象
        Target target = new Target();

        ClassLoader loader = JdkProxyDemo.class.getClassLoader();   //用来加载在运行期间动态生成的字节码
        Foo proxy = (Foo)Proxy.newProxyInstance(loader,new Class[]{Foo.class},(p,method,args) -> {
            System.out.println("before...");
            //目标.方法(参数)
            //方法.invoke(目标,参数)
            Object result = method.invoke(target,args);
            System.out.println("after...");
            return result;       //让代理也返回目标方法执行的结果
        });

//        //输出结果为
//        before...
//        target foo
//        after...
        proxy.foo();
    }
}

cglib代理实现及要点

package com.lucifer.itheima.a12;

import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;

public class CglibProxyDemo {

    // 该类不能设置成final类型  因为目标加了final 意味着将来不能有子类,但是代理就是想成为目标的子类型,所以会冲突
    static  class Target{
        // 这个方法如果是final类型的也不能增强,因为既然是子夫级的关系,那肯定是通过方法的重写来获得的增强,既然是方法重写,那对于final类型肯定不再适用,因为final的方法是不能被重写不能被继承的
        public final void foo() {
            //加了final之后的输出结果为
//            target foo
            // 不会报错,但是不具备before、after的增强功能了
            System.out.println("target foo");
        }
    }

    //代理是子类型,目标是父类型
    //跟jdk的动态代理不一样,jdk中的代理跟目标是平级的兄弟关系,他们都实现了共同的接口
    public static void main(String[] args) {
        Target target = new Target();
        Target proxy = (Target)Enhancer.create(Target.class, (MethodInterceptor) (p, method, args1, methodProxy) -> {
            System.out.println("before...");
//            Object result = method.invoke(target, args);    //用方法反射调用目标

            // methodProxy 它可以避免反射调用
//            Object result = methodProxy.invoke(target,args);     //内部没有用反射,需要目标(spring)  但是看到的效果是一样的,都是输出//
            //            before...
            //        target foo
            //        after...  但是内部确实没有用反射

            Object result = methodProxy.invokeSuper(p,args);   //内部没有用反射,需要代理    但是看到的效果是一样的,都是输出//        before...
            //        target foo
            //        after...
            System.out.println("after...");
            return result;
        });
        //第一个参数:代理的父类是什么  第二个参数,决定将来代理类中方法执行的行为
        //o指的是代理类自己,method指的是当前代理类中执行的方法,args指的是方法执行时的参数,methodProxy也可以看作是一个方法对象

        //输出结果为
//        before...
//        target foo
//        after...
        proxy.foo();
    }
}


http://www.kler.cn/a/133132.html

相关文章:

  • 【项目开发】Web App vs Native App,开发者作何选择?
  • 微信小程序 === 使用腾讯地图选点
  • 计算2的N次方
  • 第1章: 初识Pillow(PIL)
  • ADC输出码和输入电压转换关系
  • Easyui ComboBox 数据加载完成之后过滤数据
  • 使用 Hugging Face Transformer 微调 BERT
  • ElasticStack日志分析平台-ES 集群、Kibana与Kafka
  • 获取虎牙直播源
  • 什么是CDN?什么是安全加速CDN?有什么优势?
  • 【AD封装】芯片IC-SOP,SOIC,SSOP,TSSOP,SOT(带3D)
  • 企业数字化转型的好处?_光点科技
  • SELinux零知识学习十八、SELinux策略语言之类型强制(3)
  • ubuntu 无法获得锁的解决
  • 读像火箭科学家一样思考笔记02_与不确定性共舞(下)
  • 【微软技术栈】C#.NET 中的管道操作
  • 2311rust,到46版本更新
  • IOS object-c大屏图表 PNChart 折线图 曲线图
  • vue2项目修改编译巨慢
  • UiPath Studio 2023.10 Crack
  • Dart笔记:glob 文件系统遍历
  • C# params关键字
  • Linux yum 使用时提示 获取 GPG 密钥失败Couldn‘t open file RPM-GPG-KEY-EPEL-7
  • uniapp优化h5项目-摇树优化,gzip压缩和删除console.log
  • 点云从入门到精通技术详解100篇-基于点云数据的机器人装焊 过程在线测量
  • ThreadLocal优化