JDK和CGLib动态代理区别

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

CGLib动态代理:利用ASM开源包,对代理对象类的class文件加载进来,通过修改其字节码生成子类来处理。

何时使用JDK和CGLib:

1)如果目标对象实现了接口,默认情况下会采用JDK的动态代理实现AOP。

2)如果目标对象实现了接口,可以强制使用CGLIB实现AOP。

3)如果目标对象没有实现了接口,必须采用CGLIB库,Spring会自动在JDK动态代理和CGLIB之间转换。

如何强制使用CGLib实现AOP:

1)添加CGLIB库(aspectjrt-xxx.jar、aspectjweaver-xxx.jar、cglib-nodep-xxx.jar)

2)在Spring配置文件中加入<aop:aspectj-autoproxy proxy-target-class="true"/>

JDK动态代理和CGLib字节码生成的区别:

1)JDK动态代理只能对实现了接口的类生成代理,而不能针对类。

2)CGLIB是针对类实现代理,主要是对指定的类生成一个子类,覆盖其中的方法,
并覆盖其中方法实现增强,但是因为采用的是继承,所以该类或方法最好不要声明成final,
对于final类或方法,是无法继承的。

Spring如何选择用JDK还是CGLib:

)当Bean实现接口时,Spring就会用JDK的动态代理。

2)当Bean没有实现接口时,Spring使用CGlib是实现。

3)可以强制使用CGlib(在spring配置中加入<aop:aspectj-autoproxy proxy-target-class="true"/>)

代码测试如下:

我们先创建一个接口及其类

//接口类
package com.zzj.math; public interface IMathService { int add(int a,int b);
int div(int a,int b); } //及其类
package com.zzj.math; import org.springframework.stereotype.Service; @Service
public class MathService implements IMathService{ @Override
public int add(int a, int b) {
return a+b;
} @Override
public int div(int a, int b) {
return a/b;
} }

再创建一个代理类:

package com.zzj.aop;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component; @Aspect
@Component
public class MethodAop { @Before("execution(public int com.zzj.math.MathService.*(..))")
public void before(JoinPoint jp){
Signature signature = jp.getSignature();
System.out.println("The "+signature.getName()+"method begins.");
} }

spring中xml的配置:

<!--扫描-->
<context:component-scan base-package="com.zzj"></context:component-scan>
<!-- proxy-target-class为true时根据目标类来创建代理类,也就是CGlib代理,当不写或者为false时根据目标类接口来进行代理,也就是JDK代理 -->
<aop:aspectj-autoproxy proxy-target-class="false"></aop:aspectj-autoproxy>

测试:

默认使用JDK代理,而且需要获取的bean必须是接口

package com.zzj.test;

import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.zzj.math.IMathService;

public class Test {

    public static void main(String[] args){
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("application.xml");
IMathService mathService = applicationContext.getBean(IMathService.class);
System.out.println(mathService.getClass());
applicationContext.close();
}
}

当要强制使用CGLib时,我们将spring中xml的配置其对应标签属性改为true

<aop:aspectj-autoproxy proxy-target-class="true"/>)

测试类中获取的bean既可以是类也可以是接口,测试结果如下:

两种代理与目标类的关系

CGLib动态代理对象所产生的代理类是目标类的子类

System.out.println(mathService.getClass().getSuperclass());

JDK动态代理产生而的代理类与目标类没有继承关系

Class clazz = mathService.getClass();
Class [] array = clazz.getInterfaces();
for(Class c: array){
System.out.println(c.getName());
}

AOP中隐含的动态代理

一个类中的方法被@Transactional注解修饰,则Spring自动为该类创建代理类及其代理对象
我们在MathService的方法类上加上@Transactional注解并配置spring的xml文件
<!-- 配置事务管理器 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean> <!-- 启用事务注解 -->
<tx:annotation-driven transaction-manager="transactionManager"/> <!--AOP代理-->
<aop:aspectj-autoproxy proxy-target-class="false"></aop:aspectj-autoproxy>

测试结果如下:

 
 
 
 

Spring框架中的JDK与CGLib动态代理的更多相关文章

  1. Spring AOP中的JDK和CGLib动态代理哪个效率更高?

    一.背景 今天有小伙伴面试的时候被问到:Spring AOP中JDK 和 CGLib动态代理哪个效率更高? 二.基本概念 首先,我们知道Spring AOP的底层实现有两种方式:一种是JDK动态代理, ...

  2. Spring AOP中的JDK和CGLIB动态代理

    Spring在将Advice织入目标对象的Joinpoint是在运行时动态进行的.它采用的方式可能有两种,即JDK动态代理与CGLIB代理.Spring会根据具体的情况在两者之间切换. 实际情况如下: ...

  3. spring框架中JDK和CGLIB动态代理区别

    转载:https://blog.csdn.net/yhl_jxy/article/details/80635012 前言JDK动态代理实现原理(jdk8):https://blog.csdn.net/ ...

  4. 动态代理的两种方式,以及区别(静态代理、JDK与CGLIB动态代理、AOP+IoC)

    Spring学习总结(二)——静态代理.JDK与CGLIB动态代理.AOP+IoC   目录 一.为什么需要代理模式 二.静态代理 三.动态代理,使用JDK内置的Proxy实现 四.动态代理,使用cg ...

  5. 【java高级编程】JDK和CGLIB动态代理区别

    转载:https://blog.csdn.net/yhl_jxy/article/details/80635012 前言 JDK动态代理实现原理(jdk8):https://blog.csdn.net ...

  6. JDK、CGlib动态代理详解

    Java动态代理之JDK实现和CGlib实现(简单易懂)      一 JDK和CGLIB动态代理原理 1.JDK动态代理 利用拦截器(拦截器必须实现InvocationHanlder)加上反射机制生 ...

  7. JDK和CGLIB动态代理原理

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

  8. JDK和CGLIB动态代理原理区别

    JDK和CGLIB动态代理原理区别 https://blog.csdn.net/yhl_jxy/article/details/80635012 2018年06月09日 18:34:17 阅读数:65 ...

  9. JDK和CGLIB动态代理区别

    背景:虽然自己了解这两种代理的区别,但是面试时候还是答的很模糊,需要好好总结. 前言JDK动态代理实现原理(jdk8):https://blog.csdn.net/yhl_jxy/article/de ...

随机推荐

  1. 【Fine学习笔记】Xcode的快捷方式

    Xcode快捷键 文件 CMD + N: 新文件:  CMD + SHIFT + N: 新项目: CMD + O: 打开: CMD + S: 保存:  CMD + SHIFT + S: 另存为: CM ...

  2. html js中的引号

    content = "<a class='btn' href='javascript:void(0)' onclick='change('orders/orderTail.do?ode ...

  3. 知乎模拟登录,支持验证码和保存 Cookies

    import requests import time import re import base64 import hmac import hashlib import json import ma ...

  4. [网络转载 ]LoadRunner技巧之THML与URL两种录制模式分析

    loadrunner自带网站的访问 Html_based script模式 Action() { web_url("WebTours", "URL=http://127. ...

  5. Python数据类型-4 列表

    列表 列表是Python中最基本也是最常用的数据结构之一.列表中的每个元素都被分配一个数字作为索引,用来表示该元素在列表内所排在的位置.第一个元素的索引是0,第二个索引是1,依此类推. Python的 ...

  6. kafka 高吞吐量的因素

    1.顺序的方式存储数据: 2.批量发送: 3.零拷贝: 来源:咕泡学院

  7. 【PAT甲级】1024 Palindromic Number (25 分)

    题意: 输入两个正整数N和K(N<=1e10,k<=100),求K次内N和N的反置相加能否得到一个回文数,输出这个数和最小的操作次数. trick: 1e10的数字相加100次可能达到1e ...

  8. SystemVerilog for design 笔记(二)

    转载请标明出处 1. System Verilog文本值和数据类型 1.1. 增强的文本值赋值 相对于verilog,SV在文本值赋值时可以1.无需指定进制    2.赋值可以是逻辑1 用法: reg ...

  9. C++ — 后缀表达式转表达式树

    2018-07-21 16:57:26 update 建立表达式树的基本思路:方法类似由下而上建立堆的思想,所以时间复杂度为O(n),这样算法就会变得很简单,只用考虑处理需要入栈的节点和栈中的节点即可 ...

  10. 使用git下载一个项目

    1.安装好git之后创建一个库repository,用来保存git项目 2.进入repository之后,右击之后,选中 git bash here菜单选项 3.弹出命令界面之后输入命令: git c ...