spring中基于JDK和CGLIB代理在项目的应用
一、环境与问题
环境
spring boot的版本是1.2.1.RELEASE、JDK版本是1.7
问题
A服务 PeopleService
调用B服务 HelloService
,其中B服务的方法 say()
是是一个事物方法,并且B服务实现一个接口 IHelloService
。实际过程中发现A服务无法使用 @autowire
把B服务注入,但是去掉接口 `IHelloService
或者去掉 @Transactional
则可注入B服务,亦或者@Autowired
注入的类型使用IHelloService
。
二、问题思考
在解决上面问题时,我们必须要知道spring容器在开启事物的过程中使用的是AOP
技术,其实底层是通过代理实现的。在spring在选择代理时默认实现了2中代理方式一种是JDK
代理、另外一种是CGLIB
代理。其中JDK
代理是基于接口,通过接口InvocationHandler
实现的,而CGLIB
代理是基于类的,通过接口MethodInterceptor
来实现。
三、验证思考
为了验证我的解决思路是否正确,去官网查看了一下文档
10.5 Using the ProxyFactoryBean to create AOP proxies
JavaBean properties
In common with most FactoryBean implementations provided with Spring, the ProxyFactoryBean
class is itself a JavaBean. Its properties are used to:
• Specify the target you want to proxy.
• Specify whether to use CGLIB.
上面这段话的大体意思:一般情况下面我们使用FactoryBean
来提供bean
,当使用AOP
时会使用ProxyFactoryBean
来提供bean
。我们可以指定目标(即需要代理的对象),也可指定是否使用CGLIB
代理。换而言之,spring默认使用的是JDK
的代理。
再看一下实际的A服务的bean
果然是如我们猜想的那样使用了JDK
代理。
四、解决问题
指定使用CGLIB代理
@Scope(proxyMode=ScopedProxyMode.TARGET_CLASS)
再看一下结果
当我们指定用CGLIB
代理之后,发现HelloService
可以被正常进行注入,并且HelloService
也由JDK
代理对象变成了CGLIB
代理对象。
五、问题深入与扩展
随着问题的深入,我们没有解决为什么使用JDK
的代理对象不行,而使用CGLIB
代理对象却可以?
不知道大家有没有注意我上面讲过一句话“JDK
代理是基于接口...,而CGLIB
代理是基于类的...”,问题就出现在这边。下面我把基于JDK和CGLIB的对象的类名、父类名及接口名打印出来:
HelloService
基于JDK
的代理方式:
基于JDK
代理的helloService
对象的类名$Proxy44
,父类是Proxy
,接口是IHelloService
HelloService
基于CGLIB的代理方式:
基于CGLIB
代理的helloService
对象的类名是HelloService$$EnhancerBySpringCGLIB$$80f67bbd
父类是HelloService
。
至此我们终于知道了通过@Autowired
注入HelloService
对象时,使用JDK
代理时代理对象实现了IHelloService
接口,而使用CGLIB
代理时代理对象是继承了HelloService
。
spring中的代理的问题告一段落了,孔夫子讲过"举一隅,不以三隅反,则不复也"。那么我们实际项目中还有那些耳熟能详的框架也使用了代理了呢?
在web开发中不知道大家有没有注意到mybatis
中只有接口而没有实现类,其实也是使用了JDK
的代理。有兴趣的童鞋可以研究一下。
spring中基于JDK和CGLIB代理在项目的应用的更多相关文章
- Spring AOP中的JDK和CGLib动态代理哪个效率更高?
一.背景 今天有小伙伴面试的时候被问到:Spring AOP中JDK 和 CGLib动态代理哪个效率更高? 二.基本概念 首先,我们知道Spring AOP的底层实现有两种方式:一种是JDK动态代理, ...
- JAVA高级架构师基础功:Spring中AOP的两种代理方式:动态代理和CGLIB详解
在spring框架中使用了两种代理方式: 1.JDK自带的动态代理. 2.Spring框架自己提供的CGLIB的方式. 这两种也是Spring框架核心AOP的基础. 在详细讲解上述提到的动态代理和CG ...
- Spring中的JDK动态代理
Spring中的JDK动态代理 在JDK1.3以后提供了动态代理的技术,允许开发者在运行期创建接口的代理实例.在Sun刚推出动态代理时,还很难想象它有多大的实际用途,现在动态代理是实现AOP的绝好底层 ...
- 基于 JDK 的动态代理机制
『动态代理』其实源于设计模式中的代理模式,而代理模式就是使用代理对象完成用户请求,屏蔽用户对真实对象的访问. 举个最简单的例子,比如我们想要「FQ」访问国外网站,因为我们并没有墙掉所有国外的 IP,所 ...
- Spring中基于xml的AOP
1.Aop 全程是Aspect Oriented Programming 即面向切面编程,通过预编译方式和运行期动态代理实现程序功能的同一维护的一种技术.Aop是oop的延续,是软件开发中的 一个热点 ...
- 基于JDK的动态代理原理分析
基于JDK的动态代理原理分析 这篇文章解决三个问题: What 动态代理是什么 How 动态代理怎么用 Why 动态代理的原理 动态代理是什么? 动态代理是代理模式的一种具体实现,是指在程序运行期间, ...
- 在Spring中使用JDK定时器实现调度任务
在Spring中使用JDK定时器实现调度任务 作者:chszs,转载需注明.博客主页: http://blog.csdn.net/chszs 本文探讨Spring如何集成JDK的Timer定时器,实现 ...
- 【转】在Spring中基于JDBC进行数据访问时怎么控制超时
http://www.myexception.cn/database/1651797.html 在Spring中基于JDBC进行数据访问时如何控制超时 超时分类 超时根据作用域可做如下层级划分: Tr ...
- Spring 框架的概述以及Spring中基于XML的IOC配置
Spring 框架的概述以及Spring中基于XML的IOC配置 一.简介 Spring的两大核心:IOC(DI)与AOP,IOC是反转控制,DI依赖注入 特点:轻量级.依赖注入.面向切面编程.容器. ...
随机推荐
- 运行python “没有那个文件或目录3” 或 “/usr/local/bin/python3^M: bad interpreter: 没有那个文件或目录” 错误
原因 如果使用的是#!/usr/local/bin/python3这种方式,就会出现 “/usr/local/bin/python3^M: bad interpreter: 没有那个文件或目录” 错误 ...
- 数据结构|-用C#实现一个简单的链表
我们知道C#中是没有链表的,我们可以自己实现一个 整个单链表能实现的功能有: 功能 方法 返回值 备注 获取链表长度 GetLength() int 返回值是链表长度 清空链表 Clear() voi ...
- GC知识记录
2.关于Minor GC,Major GC与Full GC 1) Minor GC:即新生代的GC,指发生在新生代的垃圾收集动作.当新生代的Eden区内存不足时,就会触发Minor GC.由于对象创 ...
- Mysql推荐使用规范
一.基础规范 使用InnoDB存储引擎支持事务.行级锁.并发性能更好.CPU及内存缓存页优化使得资源利用率更高 推荐使用utf8mb4字符集无需转码,无乱码风险, 支持emoji表情以及部分不常见汉字 ...
- jfinal afterJFinalStart中执行长久循环操作的解决方案:创建新线程
很多时候,需要在jfinal中afterJFinalStart方法中,写一些需要一直循环运行的程序,做一些循环操作.但是在afterJFinalStart中,执行时间过长的话,会导致整个站点启动超时. ...
- 创建springboot项目
springboot 就是为简化spring的创建 配置 部署 运行 而创建的. springboot 直接引入依赖jar包 就行了,无须配置xml 一 创建springboot 1.创建一个mave ...
- Confluence 6 在升级过程中查看合并日志
为了监控升级的过程,你应该查看 application log 日志中的输出. 通常日志经常将会显示多个日志实例,这个实例是定义在日志的 INFO 级别的,通常格式如下: WikiToXhtmlMig ...
- 使用XStream解析复杂XML并插入数据库(一)
环境: Springboot+mysql 我只想说jpa真的超级好用,准备深入研究一下~ 导入依赖: <dependency> <groupId>org.projectlomb ...
- ASP.NET 发送邮件 SMTP
目录 // 邮件信息 对象 MailMessage mail = new MailMessage(); //新建邮件SMTP客户端 对象 用于发送 ...
- 关于微信小程序获取当前位置信息
小程序开发---获取当前位置信息 一.获取用户地理位置信息 1.配置app.json文件 { "pages": ["pages/index/index"], & ...