• 一篇文章搞懂CGlib动态代理


    前言

    对于上篇文章说的动态代理是JDK的动态代理,使用动态代理解决了静态代理耦合度高、代码冗余、不易维护等问题,但是JDK的动态代理也是有局限性的,JDK动态代理必须有接口,才可以通过反射进行动态代理,如果没有接口怎么办?铛铛铛!~CGlib闪亮登场。

    CGlib特点

    • 对于不使用接口的业务类,无法使用JDK动态代理
    • CGlib采用非常底层的字节码技术,可以为一个类创建子类,解决无接口代理问题

    CGlib怎么用

    既然不需要抽象接口了,直接搞一个实例类:

    package com.bean.ReflectDemo2;
    
    public class ProductDao {
        public void save() {
            System.out.println("保存用户...");
        }
        public void delete() {
            System.out.println("删除用户...");
        }
        public void find() {
            System.out.println("查找用户...");
        }
        public void update() {
            System.out.println("更新用户...");
        }
    }
    
    

    四个方法:增删改查,假设我们需要对find方法进行增强,在执行find方法之前进行权限校验,也就是所谓的AOP。
    首先我们需要写一个代理类:MyCglibProxy

    package com.bean.ReflectDemo2;
    
    import org.aopalliance.intercept.MethodInvocation;
    import org.springframework.cglib.proxy.Callback;
    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 MyCglibProxy implements MethodInterceptor {
    
        private ProductDao productDao;
    
        public MyCglibProxy(ProductDao productDao) {
            this.productDao = productDao;
        }
    
        public Object createProxy() {
            //1.创建核心类
            Enhancer enhancer = new Enhancer();
            //2.设置父类
            enhancer.setSuperclass(productDao.getClass());
            //3.设置回调
            enhancer.setCallback(this);
            //4.生成代理
            Object proxy = enhancer.create();
            return proxy;
        }
    
        @Override
        public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
            if ("find".equals(method.getName())){
                System.out.println("权限校验=============");
                Object o1 = methodProxy.invokeSuper(o, objects);
                return o1;
            }
            return methodProxy.invokeSuper(o,objects);
        }
    }
    
    

    可以看出来,跟JDK的动态代理其实差不多,只是名字有不同,各别调用有不同,还是比较好理解的,再来看一下测试类:

    package com.bean.ReflectDemo2;
    
    public class Demo {
        public static void main(String[] args) {
            ProductDao productDao = new ProductDao();
            ProductDao proxy = (ProductDao) new MyCglibProxy(productDao).createProxy();
            proxy.find();
        }
    }
    
    

    跟JDK动态代理其实差不多,而且更方便了。

    总结

    1、程序中应该优先对接口创建代理,便于程序解耦维护
    2、标记为final的方法,不能被代理,因为无法被覆盖

    • JDK动态代理,是针对接口生成子类,接口中方法不能使用final修饰
    • CGlib是针对目标类生产子类,因此类或方法,不能使用final的
    • Spring只支持方法连接点,不支持属性连接点
  • 相关阅读:
    Java web项目部署之SecureCRT+SecureFX的简单使用
    Ubuntu Linux系统用命令安装MySQL数据库
    Linux中操作tomcat的一些命令
    学习Java第二天
    学Java第一天
    在Windows10下在WSL中使用visual studio code
    Makefile中的变量赋值
    我见过的最好的关于typedef函数指针声明的解说
    C语言中打印格式
    Vim常用小操作【持续更新】
  • 原文地址:https://www.cnblogs.com/taobean/p/12364254.html
Copyright © 2020-2023  润新知