首页 > 其他分享 >JDK和CGLIB动态代理

JDK和CGLIB动态代理

时间:2023-04-13 15:23:34浏览次数:42  
标签:target JDK Object 代理 CGLIB public

1JDK和CGLIB动态代理的区别

JDK代理使用的是反射机制生成一个实现代理接口的匿名类,在调用具体方法前调用InvokeHandler来处理。
CGLIB代理使用字节码处理框架asm,对代理对象类的class文件加载进来,通过修改字节码生成子类。
JDK创建代理对象效率较高,执行效率较低;
CGLIB创建代理对象效率较低,执行效率高。
JDK动态代理机制是委托机制,只能对实现接口的类生成代理,通过反射动态实现接口类;
CGLIB则使用的继承机制,针对类实现代理,被代理类和代理类是继承关系,所以代理类是可以赋值给被代理类的,因为是继承机制,不能代理final修饰的类。
JDK代理是不需要依赖第三方的库,只要JDK环境就可以进行代理,需要满足以下要求:
 1.实现InvocationHandler接口,重写invoke()
 2.使用Proxy.newProxyInstance()产生代理对象
 3.被代理的对象必须要实现接口
CGLib 必须依赖于CGLib的类库,需要满足以下要求:
 1.实现MethodInterceptor接口,重写intercept()
 2.使用Enhancer对象.create()产生代理对象

做一个总结
   a.jdk代理只能对实现了接口的类进行代理,而cglib代理可以对普通类进行代理;
   b.jdk代理是通过反射的方式来实现动态代理,而cglib则是通过为目标类生成一个子类的方式来实现动态代理;
   c.由于cglib代理是为目标类生成了一个子类,并对父类方法进行增强,所以目标类不能用final修饰;


2、使用JDK还是CGLIB
1)如果目标对象实现了接口,默认情况下会采用JDK的动态代理实现AOP,可以强制使用CGLIB实现AOP
2)如果目标对象没有实现了接口,必须采用CGLIB库,spring会自动在JDK动态代理和CGLIB之间转换

3、强制使用CGLIB实现AOP的方法
1)添加CGLIB库(aspectjrt-xxx.jar、aspectjweaver-xxx.jar、cglib-nodep-xxx.jar)
2)在Spring配置文件中加入<aop:aspectj-autoproxy proxy-target-class=“true”/>

两者总结具体区别

1、Jdk动态代理:利用拦截器(必须实现InvocationHandler接口)加上反射机制生成一个代理接口的匿名类,在调用具体方法前调用InvokeHandler来处理

2、 Cglib动态代理:利用ASM框架,对代理对象类生成的class文件加载进来,通过修改其字节码生成子类来进行代理

所以:

  • 如果想要实现JDK动态代理那么代理类必须实现接口,否则不能使用;
  • 如果想要使用CGlib动态代理,那么代理类不能使用final修饰类和方法;

还有: 在jdk6、jdk7、jdk8逐步对JDK动态代理优化之后,在调用次数较少的情况下,JDK代理效率高于CGLIB代理效率,只有当进行大量调用的时候,jdk6和jdk7比CGLIB代理效率低一点,但是到jdk8的时候,jdk代理效率高于CGLIB代理。

JDK动态代理

UserService接口

public interface UserService {

    void addUser();

    void updateUser(String str);

}

UserServiceImpl实现类

public class UserServiceImpl implements UserService {
    @Override
    public void addUser() {
        System.out.println("添加用户");
    }

    @Override
    public void updateUser(String str) {
        System.out.println("更新用户信息" + str);
    }
}

UserProxy代理类,实现InvocationHandler接口重写invoke方法

public class UserProxy implements InvocationHandler {
    private Object target;

    public UserProxy(Object target) {
        this.target = target;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

        Object res = method.invoke(target, args);

        System.out.println("记录日志");

        return res;
    }
}

test测试类

public class test {
    public static void main(String[] args) {

        UserServiceImpl impl = new UserServiceImpl();
        UserProxy userProxy = new UserProxy(impl);
        UserService userService = (UserService) Proxy.newProxyInstance(impl.getClass().getClassLoader(),impl.getClass().getInterfaces(),userProxy);
        userService.addUser();
        userService.updateUser(":我是皮皮虾");
    }

}

CGlib动态代理

CGlib不像是JDK动态代理,CGlib需要导入Jar包,那么我用SpringBoot直接导入依赖

<dependency>
    <groupId>cglib</groupId>
    <artifactId>cglib</artifactId>
    <version>3.3.0</version>
</dependency>

UserServiceImpl被代理类

public class UserServiceImpl {

    public void addUser() {
        System.out.println("添加了一个用户");
    }

    public void deleteUser() {
        System.out.println("删除了一个用户");
    }

}

UserServiceCGlib代理

public class UserServiceCGlib implements MethodInterceptor {
    private Object target;

    public UserServiceCGlib() {
    }

    public UserServiceCGlib(Object target) {
        this.target = target;
    }

    //返回一个代理对象:    是 target对象的代理对象
    public Object getProxyInstance() {
        //1. 创建一个工具类
        Enhancer enhancer = new Enhancer();
        //2. 设置父类
        enhancer.setSuperclass(target.getClass());
        //3. 设置回调函数
        enhancer.setCallback(this);
        //4. 创建子类对象,即代理对象
        return enhancer.create();
    }

    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        System.out.println("增强开始~~~");
        Object result = methodProxy.invokeSuper(o, objects);
        System.out.println("增强结束~~~");
        return result;
    }

}

test测试类

public class test {

    public static void main(String[] args) {
        UserServiceCGlib serviceCGlib = new UserServiceCGlib(new UserServiceImpl());
        UserServiceImpl userService = (UserServiceImpl)serviceCGlib.getProxyInstance();
        userService.addUser();
        System.out.println();
        userService.deleteUser();
    }

}


标签:target,JDK,Object,代理,CGLIB,public
From: https://www.cnblogs.com/huigui-mint/p/17314963.html

相关文章

  • SSH实现多跳代理
    背景我们实验室有两台服务器,其中一台无法从外网访问,另一台设置了内网穿透。我平常在无法从外网访问的那台服务器上做实验,所以如果在实验室外要连接那台服务器就需要将设置了内网穿透的服务器作为跳板,通过两次ssh登进实验服务器。最近我的实验需要联网下载包,但是服务器要联网需通......
  • 如何利用Socks5代理防止爬虫被封禁
      在当前互联网环境下,爬虫已经成为了许多企业和个人获取信息的重要途径。然而,很多网站都设置了反爬虫机制,导致许多爬虫被封禁或者被限制访问。在这种情况下,利用Socks5代理是一个不错的解决方案。  Socks5代理是一种网络协议,它能够将网络请求通过代理服务器进行转发。Socks5......
  • ASEMI代理AD9951YSVZ原装ADI车规级AD9951YSVZ
    编辑:llASEMI代理AD9951YSVZ原装ADI车规级AD9951YSVZ型号:AD9951YSVZ品牌:ADI/亚德诺封装:HTQFP-48批号:2023+引脚数量:48安装类型:表面贴装型AD9951YSVZ汽车芯片特征400MSPS内部时钟速度集成14位数模转换器(DAC)32位调整字1kHz偏移时的相位噪声≤−120dBc/Hz(DAC输出)出色......
  • ASEMI代理AD9833BRMZ-REEL7原装ADI车规级AD9833BRMZ-REEL7
    编辑:llASEMI代理AD9833BRMZ-REEL7原装ADI车规级AD9833BRMZ-REEL7型号:AD9833BRMZ-REEL7品牌:ADI/亚德诺封装:MSOP-10批号:2023+安装类型:表面贴装型引脚数量:10类型:车规级芯片工作温度:−40°C至+105°CAD9833BRMZ-REEL7特性AD9833BRMZ-REEL7是一种低功耗可编程波形能够产生......
  • Linux环境jdk安装教程及详细步骤
    下载jdk包:下载地址:https://www.oracle.com/cn/java/technologies/javase/javase8u211-later-archive-downloads.html这里点击下载后,需要登录才可以下载,没有帐号就注册一下即可。将下载的文件放至服务器/usr/local/jdk目录下:xShell连接linux,进入此目录,执行解压命令:tar-xvfjdk-8u35......
  • JdkProxy的进阶知识
    如果想增强一个方法的功能,无非就是直接在方法体内直接修改。但这也无非给一些有代码洁癖人士一丝丝不悦!于是乎我们即不想在原来的代码里修改,又不想把原有的代码重新写一次,那么前辈们就发明了代理.注意:本文以JdkProxy为基础展开所有描述!参与对象那么一个代理过程参与的对象有......
  • jdk1.8 LocalDate、LocalTime、LocalDateTime
    LocalDate、LocalTime、LocalDateTime区别LocalDate使用基础使用LocalDate、LocalTime、LocalDateTime区别LocalDate、LocalTime、LocalDateTime是java8对日期、时间提供的新接口。相比于SimpleDateFormat,线程安全。LocalDate用于日期的计算LocalTime用于时刻的......
  • 通过代理使用人工智能服务保姆级教程
    今年,以OpenAI(ChatGPT)、微软Microsoft(NewBing),谷歌Google(Bard)为代表的通用人工智能横空出世。其表现出的智能水平和无所不知的能力令人叹为观止,能够高分通过各类高考和专业考试,能够大大提升文字工作者和程序员的生产力。将会对教育、咨询、中介、IT、软件、设计、制造等行业产生......
  • ASEMI代理AD9833BRMZ-REEL原装ADI车规级AD9833BRMZ-REEL
    编辑:llASEMI代理AD9833BRMZ-REEL原装ADI车规级AD9833BRMZ-REEL型号:AD9833BRMZ-REEL品牌:ADI/亚德诺封装:MSOP-10批号:2023+引脚数量:10安装类型:表面贴装型AD9833BRMZ-REEL汽车芯片AD9833BRMZ-REEL特征数字可编程频率和相位3V时的12.65mW功耗0MHz至12.5MHz输出频率范围28位分辨率:0.1......
  • AD633JRZ-ASEMI代理ADI亚德诺AD633JRZ车规级芯片
    编辑-ZAD633JRZ芯片参数:型号:AD633JRZ总误差:±1%标度电压错误:±0.25%电源干扰:±0.01%输出偏移电压:±5mV小信号带宽:1MHz斜率:20V/µs沉降时间达到1%:2µs宽带噪声:1mVrms输出电压摆幅:±11V短路电流:30mA信号电压范围:±10V差动电阻:10MΩ额定性能电源电压:±15V  AD63......