一篇文章搞懂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只支持方法连接点,不支持属性连接点
发布了54 篇原创文章 · 获赞 82 · 访问量 9万+

猜你喜欢

转载自blog.csdn.net/u011679785/article/details/99218116