从一而终只使用一种Spring编程风格
编程技术  /  houtizong 发布于 3年前   53
现在很常见的就是不管如何先定义接口,如下所示:
package com.sishuok;public interface Interface { public void sayHello();}
然后定义实现,真的有必要吗?思考下。
package com.sishuok;public class Impl implements Interface { @Override public void sayHello() { System.out.println("hello"); }}
Bean用于注入Impl,其实此处是错误的,因为定义了接口,应该注入接口的。
package com.sishuok;public class Bean { private Impl impl; public Bean() { } public Bean(final Impl impl) { this.impl = impl; }}
怎么实现无所谓,就是为了生成代理对象,重现问题。
package com.sishuok;public class Aspect { public void before() { System.out.println("==before"); }}
<bean id="aspect" class="com.sishuok.Aspect"/> <aop:config> <aop:aspect ref="aspect"> <aop:before method="before" pointcut="execution(* com.sishuok.Impl.*(..))"/> </aop:aspect> </aop:config> <bean id="impl" class="com.sishuok.Impl"/> <bean id="b" class="com.sishuok.Bean"> <constructor-arg name="impl" ref="impl"/> </bean>
配置文件很简单。 一个AOP切面会横切Impl,即生成Impl代理,而Bean会注入Impl。
测试类很简单,只需要加载配置文件即可。
@RunWith(SpringJUnit4ClassRunner.class)@ContextConfiguration(locations={"classpath:spring-config.xml"})public class BeanIT { @Autowired private Bean bean; @Test public void test() { System.out.println("=hello test"); }}
整段代码很简单,应该能猜到是嘛问题。
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'b' defined in class path resource [spring-config.xml]: Could not resolve matching constructor (hint: specify index/type/name arguments for simple parameters to avoid type ambiguities)
这个异常让人疑惑,因为它告诉你说可能是构造器的问题,所以可能把我们带坑里看不到真实问题。
主要原因是:
我们实际定义了两个构造器:
1、一个空参的:public Bean()
2、一个带Impl参数的:public Bean(final Impl impl)
如果把第一个构造器删除就会得到真实的异常:
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'b' defined in class path resource [spring-config.xml]: Unsatisfied dependency expressed through constructor argument with index 0 of type [com.sishuok.Impl]: Could not convert constructor argument value of type [$Proxy8] to required type [com.sishuok.Impl]: Failed to convert value of type '$Proxy8 implementing com.sishuok.Interface,org.springframework.aop.SpringProxy,org.springframework.aop.framework.Advised' to required type 'com.sishuok.Impl'; nested exception is java.lang.IllegalStateException: Cannot convert value of type [$Proxy8 implementing com.sishuok.Interface,org.springframework.aop.SpringProxy,org.springframework.aop.framework.Advised] to required type [com.sishuok.Impl]: no matching editors or conversion strategy found
很明显是注入问题,见到$Proxy8 我们就能猜到是JDK动态代理(这个在《spring的二次代理原因及如何排查》说过),即它不能转换为实际的com.sishuok.Impl,问题很明显了.
此处还有另一个问题:关于按照构造器参数名注入时,具体参考《【第三章】 DI 之 3.1 DI的配置使用 ——跟我学spring3》中的构造器注入部分。
1、要么构造器注入接口,即public Bean(final Interface impl)
2、要么使用CGLIB类代理
1、知道自己使用的是啥编程风格:
2、知道自己使用的啥代理:
明确自己的风格,从一而终,不要为了玩玩都用上,Spring已经很庞大且复杂了,,使用Spring出问题最多的就是AOP部分,遇到AOP问题。可参考《请不要再使用低级别的AOP API》
官方文档还是要看的,当然刚开始可能比较困难,但是坚持几次以后就轻松了,出问题先看文档,接着翻javadoc,基本能搞定,当然读一读源码对日常开发的调错还是很有帮助的。
请勿发布不友善或者负能量的内容。与人为善,比聪明更重要!
技术博客集 - 网站简介:
前后端技术:
后端基于Hyperf2.1框架开发,前端使用Bootstrap可视化布局系统生成
网站主要作用:
1.编程技术分享及讨论交流,内置聊天系统;
2.测试交流框架问题,比如:Hyperf、Laravel、TP、beego;
3.本站数据是基于大数据采集等爬虫技术为基础助力分享知识,如有侵权请发邮件到站长邮箱,站长会尽快处理;
4.站长邮箱:[email protected];
文章归档
文章标签
友情链接