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依赖注入 特点:轻量级.依赖注入.面向切面编程.容器. ... 
随机推荐
- acm:屁屁上的巴掌
			涉及算法:深度搜索 题目: 题目描述 小新是个调皮的孩子,他总是会把衣服搞脏,他的妈妈美伢非常的生气,于是在<和妈妈的约定条款>加上了第三百七十七条:小新衣服上每有一块污渍妈妈就会打小新的 ... 
- 《R语言入门与实践》第一章:R基础
			前言 本章介绍了 R 语言的基础知识 界面: 使用命令 “ R “进行命令行的实时编译 对象 定义: 用于储存数据的,设定一个名称 格式: a <- 1:6 命名规则: 规则1:不能以数字开头规 ... 
- label标签内含有input元素,点击事件会触发两次
			**label标签内含有input元素,点击事件会触发两次** 如果你的结构是label内写input实现点击文字时候input也有相应.并且,把事件设置在了label上,那么就会执行两次了. //h ... 
- React文档(二十一)协调
			React提供了一个声明式地API因此你不用担心每一次更新什么东西改变了.这使得开发应用变得简单,但是这个东西在React中如何实现的并不是很明显.这篇文章会解释我们在React的算法中所做的选择以便 ... 
- hadoop知识点总结
			(一).hadoop的内置数据类型都实现了writablecompareable,以便序列化和网络传输及文件存储 a自定义数据类型作为输入 1.实现writable接口 2.如果给数据需要比较大小时, ... 
- nginx插入lua脚本访问redis
			目标:收集用户日志 流程: 浏览器端get方法将数据传到nginx服务 nginx收集到数据,执行内嵌lua脚本,访问redis,根据token获得用户id 将日志信息存入文件 1.nginx安装,参 ... 
- hadoop hdfs 数据迁移到其他集群
			# hadoop fs -cat /srclist Warning: $HADOOP_HOME is deprecated. hdfs://sht-sgmhadoopcm-01:9011/jdk-6u ... 
- springboot使用fastjson中文乱码解决方法 【转载】
			以前使用fastjson替换jackson时,没有直接在页面打印过json,都是js使用没有出现乱码,偶然 打印出来出现了中文乱码 之前使用的配置方式 @Configuration public cl ... 
- 爬虫(五)requests模块2
			引入 有些时候,我们在使用爬虫程序去爬取一些用户相关信息的数据(爬取张三“人人网”个人主页数据)时,如果使用之前requests模块常规操作时,往往达不到我们想要的目的,例如: #!/usr/bin/ ... 
- jquery横向纵向鼠标滚轮全屏切换
			html <!DOCTYPE html> <html lang="zh"> <head> <meta charset="UTF- ... 
