前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Spring的动态代理机制时为什么必须指定接口

Spring的动态代理机制时为什么必须指定接口

作者头像
浩Coding
发布2019-07-03 11:45:16
7460
发布2019-07-03 11:45:16
举报
文章被收录于专栏:浩Coding

这是一个常见的Spring配置文件:

代码语言:javascript
复制
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd">
  <!-- 将指定类TestDIDaoImpl配置给Spring,让Spring创建其实例 -->
  <bean id="myTestDIDao" class="dao.TestDIDaoImpl" />
  <!-- 使用构造方法注入 -->
  <bean id="testDIService" class="service.TestDIServiceImpl">
    <!-- 将myTestDIDao注入到TestDIServiceImpl类的属性 testDIDao上-->
    <constructor-arg index="0" ref="myTestDIDao"/>
  </bean>
</beans>

使用动态代理的时候,下面明明已经指定了要代理的对象,为什么上面还要多此一举指定这个对象所实现的接口呢?

原因是:Spring动态代理功能的实现是基于java的动态代理机制

主要的原理是使用Proxy.newProxyInstance()方法创建一个代理对象来代理指定的类,查阅JDK文档这个方法有三个参数:

newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)

第一个参数为要代理的类,第二个参数为这个类的接口,第三个暂且不管。

原来java实现动态代理的时候要求必须有接口类,导致spring也这么向我们要求了。

我们再来看看 越過山丘 博主的解释:

原文链接:https://www.cnblogs.com/lee10010/p/7888121.html

首先说明,注入的对象确实为实现类的对象。(并不是实现类的代理对象,注入并不涉及代理)

如果只是单纯注入是可以用实现类接收注入对象的,但是往往开发中会对实现类做增强,如事务,日志等,实现增强的AOP技术是通过动态代理实现的,而Spring默认是JDK动态代理,对实现类对象做增强得到的增强类与实现类是兄弟关系,所以不能用实现类接收增强类对象,只能用接口接收。如:

代码语言:javascript
复制
//接口:IA

//实现类:AImpl

//增强类:AImplProxy

AImpl aImpl = new AImpl();

//通过JDKProxyFactory创建代理对象
JDKProxyFactory factory = new JDKProxyFactory(aImpl);
//这个增强类对象aImplProxy 只能强转为IA,而不能转为AImpl,
//因为JDK代理得到的AImplProxy类与AImpl是兄弟关系而非父子
AImplProxy aImplProxy = factory.createProxy();

由于以上原因,如果将对象注入给实现类而非接口的话,在代理时就会报错。解决方法,让Spring强制使用Cglib代理

代码语言:javascript
复制
<aop:aspectj-autoproxy proxy-target-class="true"/>

cglib代理类和实现类之间是父子关系,自然可以用父类(实现类)去接收子类对象(代理类对象即增强类对象)

不过应该不会需要这么做,使用接口本来就是解耦的,你直接用实现类接收注入对象岂不是失去了注入的意义。(为什么不直接new一个呢?)

参考文章:

https://blog.csdn.net/withiter/article/details/5474407

https://bbs.csdn.net/topics/390683139

https://blog.csdn.net/hzy38324/article/details/78013136

https://www.cnblogs.com/lee10010/p/7888121.html

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-03-13,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 浩Coding 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档