• Spring动态代理的两种方式


    Spring动态代理的两种方式

    1. Spring创建的动态代理类在哪?

    Spring 框架在运行时,通过字节码技术,在jvm创建的,运营在jvm内部,等程序结束后,会和jvm一起消失。

    1.1 什么叫动态字节码技术?

    通过第三方动态字节码框架,在jvm中创建对应类的字节码,进而创建对象,当虚拟机结束,动态字节码跟着消失。==
    结论:
    动态代理不需要定义类文件,都是在jvm运行过程中创建的,所以不会造成静态代理,类文件数量过多,影响项目管理的问题。
    第三方动态字节码框架:ASM,javassist ,cglib

    2.JDK的动态代理

    2.1 Proxy.newProxyInstance法参数详解

    Proxy.newProxyInstance(ClassLoader, Interfaces, handler);
    
    • 1

    参数1ClassLoader:借用一个类加载器,创建代理类,的class对象,进而可以创建代理对象。
    参数2Interfaces:原始对象的接口,例如:

    TestService testService = new TestServiceImpl();
    //参数2Interfaces:testService.getClass().getInterfaces();
    
    • 1
    • 2

    参数3:handler 即 invocationHandler
    作用:用于书写额外功能,额外功能运行在原始方法之前 ,之后,抛出异常。
    例如:

     InvocationHandler handler = new InvocationHandler() {
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            System.out.println("------proxy  log  before --------");
            //原始方法运行
            Object ret = method.invoke(testService, args);
            System.out.println("------proxy  log  after --------");
            return ret;
        }
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    上述代码中各个参数的含义:
    返回值:Object:原始方法的返回值。
    参数:proxy: 可忽略,代表的是代理对象;
    method:额外功能所增加给的那个原始方法,可调用invoke()方法执行原始方法
    args[]:原始方法的参数

    2.1 编码

    前置条件:
    一个接口和一个接口的实现类,例如:
    接口:

    public interface TestService {
    
        boolean login(String username, String passoword);
    }
    
    • 1
    • 2
    • 3
    • 4

    实现类:

    public class TestServiceImpl implements TestService {
        @Override
        public boolean login(String username, String passoword) {
            System.out.println("username = " + username + "password = " + passoword);
            return true;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    开始编写动态代理:

    public class TestProxy {
     public static void main(String[] args) {
         //1. 创建原始对象
         TestService testService = new TestServiceImpl();
         //2. 创建JDK动态代理
         InvocationHandler handler = new InvocationHandler() {
             @Override
             public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                 System.out.println("------proxy  log  before --------");
                 //原始方法运行
                 Object ret = method.invoke(testService, args);
                 System.out.println("------proxy  log  after --------");
                 return ret;
             }
         };
    
         /*
           ClassLoader loader,借用一个类加载器 创建代理类的class对象  ,进而可以创建代理对象
           Class[] interfaces,
           InvocationHandler h
          */
         TestService testServiceProxy = (TestService) Proxy.newProxyInstance(TestServiceImpl.class.getClassLoader(), testService.getClass().getInterfaces(), handler);
         testServiceProxy.login("123", "123");
     }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    运行结果:
    在这里插入图片描述

    3. CGlib的动态代理

    CGlib创建动态代理的原理:继承关系创建代理对象,原始类作为类,代理类作为类,这样既可以保证2者法致,同时在代理类中提供新的实现(额外功能+原始法);

    3.1 编码

    前置条件跟上面一样

    public class TestCglib {
        public static void main(String[] args) {
            // 1. 创建原始对象
            TestService testService = new TestService();
            //2 .通过cglib创建动态代理对象
            Enhancer enhancer = new Enhancer();
            enhancer.setClassLoader(testService.getClass().getClassLoader());
            enhancer.setSuperclass(testService.getClass());
            MethodInterceptor methodInterceptor = (o, method, args1, methodProxy) -> {
                //等同于 InvocationHandler ---invoke
                System.out.println(" log= ");
                Object invoke = method.invoke(testService, args1);
                return invoke;
            };
    
            enhancer.setCallback(methodInterceptor);
    
            TestService o = (TestService) enhancer.create();
            o.login("yjy", "123");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    运行结果:
    在这里插入图片描述

    4. 总结

    1. JDK动态代理 Proxy.newProxyInstance() 通过接创建代理的实现类
    2. Cglib动态代理 Enhancer 通过继承类创建的代理类

    若有错误,希望大佬指出。

    对你有帮助给点个??再走呗。

    先自我介绍一下,小编13年上师交大毕业,曾经在小公司待过,去过华为OPPO等大厂,18年进入阿里,直到现在。深知大多数初中级java工程师,想要升技能,往往是需要自己摸索成长或是报班学习,但对于培训机构动则近万元的学费,着实压力不小。自己不成体系的自学效率很低又漫长,而且容易碰到天花板技术停止不前。因此我收集了一份《java开发全套学习资料》送给大家,初衷也很简单,就是希望帮助到想自学又不知道该从何学起的朋友,同时减轻大家的负担。添加下方名片,即可获取全套学习资料哦

  • 相关阅读:
    编译概念总结
    感知机算法之Python代码实现
    巴州阳光志愿者服务协会党支部开展 第十一季“衣旧情深”爱心 活动
    Eclipse的最常用的快捷键(一表搞定)
    netty系列之:netty中的核心编码器bytes数组
    APM建设踩了哪些坑?去哪儿旅行分布式链路追踪系统实践
    ARM DIY(九)陀螺仪调试
    MT4选网页版还是桌面版?anzo capital昂首资本分析优劣
    神经网络过拟合怎么解决,神经网络过拟合怎么办
    图论模板详解
  • 原文地址:https://blog.csdn.net/bhegi_seg/article/details/126064371