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的代理。有兴趣的童鞋可以研究一下。

 

 

转载于:https://www.cnblogs.com/stone-lss/p/10220290.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值