为什么spring注入接口正确而注入接口的实现类错误?

在做spring和mybatis整合的时候出现的问题。

这个问题的根本在于动态代理类生成代理对象。动态代理有两种的实现方式jdk和cglib的方式,这两种方式也是A实现原理。

原因所在:出现如果直接注入实现类会出现没有对应的bean,因为我们通过实现类来继承的接口,然而,必须使用jdk提供的动态代理放法,而不使用接口直接对实现类进行注入,则为cglib的注入,而不能既继承接口又使用实现类来注入的方式,这样两种代理类都是没有办法使用的。

解决方案:1.直接通过jdk去生成动态代理类,(原理要求必须实现接口)

   2.通过cglib去实现接口,直接使用代理类,而不能实现接口。
 

 

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

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


//接口:IA

//实现类:AImpl

//增强类:AImplProxy

AImpl aImpl = new AImpl();

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

  由于以上原因,如果将对象注入给实现类而非接口的话,在代理时就会报错。

解决方法,让Spring强制使用Cglib代理:

<aop:aspectj-autoproxy proxy-target-class="true"/>
  cglib代理类和实现类之间是父子关系,自然可以用父类(实现类)去接收子类对象(代理类对象即增强类对象)。

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

 

被人随意问了一句,为何每个service层都要写一个接口呢,多麻烦~虽然想说点什么,但是又不知道从何说起,只好从新整理一下思绪.

情景1:在开源框架中有很多这种情况,就是某个功能支持用户自定义扩展.说白了,它提供了一个接口,我们只需要实现这个接口,把我们自己的实现逻辑补上,就可以让框架按照我们的逻辑来执行.问题来了,框架的作者并不知道我们的实现类是什么,如果不定义一个接口,那么要如何在框架中调用我们的实现类呢?

情景2:我和同事分别做项目的2个不同功能模块,但是同事的功能中却需要调用我这头实现的部分逻辑.为了让他有一个"占位符"可用,我是不是应该快速的写个接口扔给他呢?

情景3:一个适配器功能,或是说一个简单的工厂类,如果没有定义接口,那么面对众多实现类,要如何统一操作呢?

情景4:想让项目的代码符合某种"规范",但是又不可能看着别人写代码吧,那好办,先出一套接口,然后你们就看着办~

情景5:java中没有多继承,但是可以多实现接口,那么就有一件很有趣的事情了,一个实现类可以实现多个接口,然后此时接口可以有选择的暴露实现类的部分方法,做到"窄化"实现类功能的目的.

当然例子还有很多..这些情况其实可以说是接口好处的体现,所以java有面向接口编程的建议.但是说回Service层一定要有接口吗?那到未必,因为说到底,多一个接口仅仅是扩展性和某些情况下有优势,但是是否会用到接口的便利性,不确定的情况下我们未必一定要为"可能"买单.只是多写那几行代码,付出一点就可能避免"未来"的大"麻烦",何乐而不为!?

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值