springboot团队之所以默认的代理模式设置成cglib代理,看看spring的官方团队是怎么解释的

This was changed in 1.4 (see https://github.com/spring-projects/spring-boot/issues/5423). We’ve generally found cglib proxies less likely to cause unexpected cast exceptions.

他们认为使用cglib更不容易出现转换错误

整体逻辑

先捋一下整体逻辑哈

代码演示:

interface IUserService{void getUser();
}
class UserServiceImpl implements IUserService{@Overridepublic void getUser() {System.out.println("usersevice的getUser方法");}
}

jdk动态代理

通过上面的图,在bean后置处理器的时候拿到当前的bean对象然后进行代理,最终返回代理对象;

//创建jdk代理的方法

  /*** 第一种 jDk*/public static Object createJdkProxy(Object currentObj){return Proxy.newProxyInstance(SpringProxyDemo.class.getClassLoader(),currentObj.getClass().getInterfaces(),new Invoke(currentObj));}

handler 在方法前后需要增强的功能 ;

class Invoke implements InvocationHandler {private Object o;//真实的对象public Invoke(Object object){this.o = object;}@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println("方法前后打印日志:--------before");Object invoke = method.invoke(o, args); //执行对象的方法System.out.println("方法前后打印日志--------after");return invoke;}
}

模拟一下:

通过反射创建对象 : userService

aop增强打印日志: userService对象传入handler里面 ,该对象才是真正执行方法的对象,返回代理对象

进行方法调用

public static void main(String[] args) throws Exception{//1.这里类似于spring,简写哈:Spring - BeanDefine 根据里面的class信息进行反射创建对象Class<UserServiceImpl> userServiceClass = UserServiceImpl.class;UserServiceImpl userService = userServiceClass.newInstance();//这里相当于spring的bean对象,现在要在service方法前后增加日志,所以要用aop, 调用bean的后置处理器//创建代理对象 - 并返回,此时bean工厂里面的实例就是该代理对象IUserService userServiceProxy = (IUserService)createJdkProxy(userService);//调用方法userServiceProxy.getUser();}

看一下执行结果:

CGLB:

通过上面的图,在bean后置处理器的时候拿到当前的bean对象然后进行代理,最终返回代理对象;

class Inteceptor implements MethodInterceptor{private Object obj;public Inteceptor(Object object){this.obj = object;}@Overridepublic Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {System.out.println("CGLB-方法前后打印日志:--------before");Object invoke = methodProxy.invoke(obj, objects); //执行对象的方法System.out.println("CGLB-方法前后打印日志--------after");return invoke;}
}
  public static Object createCGLBProxy(Object currentObj){Enhancer enhancer = new Enhancer();// 设置enhancer对象的父类enhancer.setSuperclass(currentObj.getClass());// 设置enhancer的回调对象enhancer.setCallback(new Inteceptor(currentObj));// 创建代理对象return  enhancer.create();}
public static void main(String[] args) throws Exception{//1.这里类似于spring,简写哈:Spring - BeanDefine 根据里面的class信息进行反射创建对象Class<UserServiceImpl> userServiceClass = UserServiceImpl.class;UserServiceImpl userService = userServiceClass.newInstance();//这里已经创建对象了,现在要在service方法前后增加日志,所以要用aop, 调用bean的后置处理器//创建代理对象 - 并返回,此时bean工厂里面的实例就是该代理对象UserServiceImpl cglbProxy = (UserServiceImpl)createCGLBProxy(userService);cglbProxy.getUser();}

容易出现转换错误

原因: jdk动态生成的代理类, 是实现了接口,所以返回的类型是我们实现类的接口类型,如果我们在日常使用spring中,使用的是实现类的类型的话就会报错,如下:

看下面的例子可以看到,我使用的是jdk代理,custDeadLineWarnService创建了代理对象,返回的是

custDeadLineWarnService实现的接口类型

所以我们如果直接写CustDeadLineWarnServiceImpl就会报错:该类型不能转为接口类型

CGLB:

而 CGLIB 就不存在这个问题。因为 CGLIB 是通过继承生成子类来实现的,代理对象无论是赋值给接口还是实现类这两者都是代理对象的父类

spring boot 动态代理相关推荐

  1. Spring AOP动态代理实现,解决Spring Boot中无法正常启用JDK动态代理的问题

    Spring AOP动态代理实现,解决Spring Boot中无法正常启用JDK动态代理的问题 参考文章: (1)Spring AOP动态代理实现,解决Spring Boot中无法正常启用JDK动态代 ...

  2. spring的动态代理,碰到了一个类型转换的问题:java.lang.ClassCastException: com.sun.proxy.$Proxy16 cannot be cast to com.

    spring的动态代理,碰到了一个类型转换的问题: java.lang.ClassCastException: com.sun.proxy.$Proxy16 cannot be cast to com ...

  3. spring boot 动态切换数据源实现多租户开发

    之前的文章有介绍过spring boot 动态切换数据源spring boot 动态切换数据源(数据源信息从数据库中读取)_lgq2016的博客-CSDN博客,今天简单介绍一下动态数据源切换实战,主要 ...

  4. Spring Boot 动态数据源(多数据源自己主动切换)

    本文实现案例场景: 某系统除了须要从自己的主要数据库上读取和管理数据外.另一部分业务涉及到其它多个数据库,要求能够在不论什么方法上能够灵活指定详细要操作的数据库. 为了在开发中以最简单的方法使用,本文 ...

  5. Spring Boot 动态数据源(Spring 注解数据源)

    本文实现案例场景: 某系统除了需要从自己的主要数据库上读取和管理数据外,还有一部分业务涉及到其他多个数据库,要求可以在任何方法上可以灵活指定具体要操作的数据库. 为了在开发中以最简单的方法使用,本文基 ...

  6. Spring CGLlB动态代理

    JDK 动态代理使用起来非常简单,但是有一定的局限性,这是因为 JDK 动态代理必须要实现一个或多个接口,如果不希望实现接口,则可以使用 CGLIB 代理. CGLIB(Code Generation ...

  7. Spring JDK动态代理

    JDK 动态代理是通过 JDK 中的 java.lang.reflect.Proxy 类实现的.下面通过具体的案例演示 JDK 动态代理的使用. 1. 创建项目 在 MyEclipse 中创建一个名称 ...

  8. Spring Boot 动态修改定时任务cron参数

    动态修改定时任务cron参数 不需要重启应用就可以动态的改变Cron表达式的值不能使用@Scheduled(cron = "${jobs.cron}")实现 动态定时任务类Dyna ...

  9. Spring AOP动态代理

    导入依赖: <dependency><groupId>org.springframework</groupId><artifactId>spring-a ...

  10. Spring的动态代理原理

    Spring动态代理原理 Spring动态代理有两种:CGLIB动态代理和JDK动态代理. JDK动态代理可以代理接口,不能代理没有实现接口的类:而CGLIB通过字节码技术可以动态生成被代理类的子类, ...

最新文章

  1. python升级版本命令-pythonpip命令版本过低问题版本升级问题
  2. C/C++程序基础 (九)排序算法简述
  3. STM32 KEIL 串口打印printf使用详解
  4. 【c++手记】句柄类智能指针
  5. python 函数前有一个下划线_【Python】怎么写好一个 Python 函数?
  6. 从Docker 到Jenkins 到Ansible的部署经验 1
  7. 12 组合与继承、CSS Module
  8. 鸟哥学习笔记---网络驱动器设备iSCSI
  9. nginx fastcgi python_Nginx + webpy 和FastCGI搭建webpy环境
  10. 【渝粤题库】陕西师范大学200991教育统计学作业(高起本)
  11. Mac文本操作实用技巧,快速提升你的工作效率!
  12. 【直播预告】腾讯广告实时策略数据框架建设
  13. [第五组] 典型用户 +用例+功能说明书+技术说明书 2017.07.25版
  14. html武侠文字游戏源码,执剑行!最新武侠文字mud游戏
  15. 解决aspx页面中关键词(keywords)和描述(descript)不显示问题
  16. Android集成环信IM,实现聊天置顶功能
  17. 展翅翱翔之时 (はばたきのとき)
  18. 某音漂亮小姐姐视频合集一键下载,想看就看!
  19. 计算机专业实习目的与意义,计算机专业实习目的及意义
  20. 彩票走势图xcode源码

热门文章

  1. 应用数学计算机数学,常用数学应用软件
  2. linux查询文件夹大小
  3. linux 查看文件夹大小
  4. 天书 kdb+之q语言
  5. rf扫描枪_RF枪(RF手持扫描枪)是什么,有什么用途?
  6. python字符串怎么加绝对值_每日一练 | Python绝对值有哪些实例?
  7. 一个 可以在线播放 m3u8 的网页
  8. H5加壳APP发布Android、IOS应用(证书响应文件制作)
  9. 原来win7专业版64位 MBR方式安装win10专业版_x86
  10. 解决U盘写保护,成功擦除