Spring学习:静态代理到动态代理

动态代理:cglib,jdk,区别联系,个人感受

静态代理

为每个Service对象写一个ServiceProxy。在ServiceProxy中写一些原本在Service中的重复性的冗余代码,使得在Service对象中能够更加专注于真正的业务代码。
但是在实际的项目中,会出现很多的Service对象,从而导致静态代理不仅没有减少我们的工作量,反而增加了更多的冗余代码。

什么是动态代理

java动态代理是利用反射机制生成一个实现代理接口的匿名类,在调用具体方法前调用InvokeHandler来处理。
具体使用场景可以在日志管理、权限认证、安全检查和事务控制等类似情景中使用。

动态代理底层实现

jdk

概述:通过Proxy.newProxyInstance(ClassLoader,Class<?>[] args,InvocationHandler)方法,先生成新的class文件,然后加载到jvm中,然后使用反射,先用class取得他的构造方法,然后使用构造方法得到他的一个实例。
mybatis获取dao时用的底层原理也是动态代理。

//使用动态代理对象:指的是在程序运行的过程中,动态地通过代码的方式为指定的类生成Proxy代理对象。
        /*Proxy用于生成动态代理
            参数1:ClassLoader 类加载器,底层代码通过反射机制,通过类加载器获取字节码信息创建代理对象
            参数2:Class[] 目标对象(被代理的对象)的接口类型的数组
                    这里之所以用数组是因为一个类可以继承多个接口
                    注:这里的代理类代理的是接口,而不是实现类;在invoke方法是传入目标对象,才确定是具体为哪个类代理
            参数3:invocationHandler   invoke方法 在执行真正的目标对象的函数时,会先执行代理对象中的功能,因此
                    可以在此书写额外功能
            返回值:创建好的动态代理对象
         */
//      被代理对象|目标对象
        final UserService userService = new UserServiceImpl();
//        参数1:
        ClassLoader classLoader = userService.getClass().getClassLoader();
//        ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
//        参数2:
        Class[] classes = {UserService.class};
//        参数3:
        UserService proxy = (UserService) Proxy.newProxyInstance(classLoader, classes, new InvocationHandler() {
//            通过动态代理对象调用被代理对象的函数方法时,会优先指定invoke方法
//            参数1:当前代理对象
//            参数2:当前代理对象调用的方法
//            参数3:当前代理对象调用的方法的参数
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                Object invoke=null;
                try{
                    System.out.println("开启事务");
                    invoke = method.invoke(userService, args);
                    System.out.println("提交事务");
                }catch (Exception e){
                    System.out.println("回滚事务");
                }
                return invoke;
            }
        });
        proxy.save("test");

这里生成代码的过程中,都使用了缓存,jdk自带的使用了weakReference引用,而cglib使用的直接是 WeakHashMap,基本也类似。

两者区别

名称备注
静态代理简单,代理模式,是动态代理的理论基础,常见使用在代理模式
jdk动态代理需要有顶层接口才能使用,使用反射完成,使用了动态生成字节码技术。但是在只有顶层接口的时候也可以使用,例如mybatis的mapper文件是代理。
cglib动态代理可以直接代理类,使用了ASM字节码操纵框架。不能对final类进行继承。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值