`
jinnianshilongnian
  • 浏览: 21504216 次
  • 性别: Icon_minigender_1
博客专栏
5c8dac6a-21dc-3466-8abb-057664ab39c7
跟我学spring3
浏览量:2418708
D659df3e-4ad7-3b12-8b9a-1e94abd75ac3
Spring杂谈
浏览量:3008818
43989fe4-8b6b-3109-aaec-379d27dd4090
跟开涛学SpringMVC...
浏览量:5639508
1df97887-a9e1-3328-b6da-091f51f886a1
Servlet3.1规范翻...
浏览量:259935
4f347843-a078-36c1-977f-797c7fc123fc
springmvc杂谈
浏览量:1597334
22722232-95c1-34f2-b8e1-d059493d3d98
hibernate杂谈
浏览量:250226
45b32b6f-7468-3077-be40-00a5853c9a48
跟我学Shiro
浏览量:5858970
Group-logo
跟我学Nginx+Lua开...
浏览量:702014
5041f67a-12b2-30ba-814d-b55f466529d5
亿级流量网站架构核心技术
浏览量:785228
社区版块
存档分类
最新评论

从一而终只使用一种Spring编程风格

 
阅读更多

代码

1、组件

现在很常见的就是不管如何先定义接口,如下所示:

 

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;
    }
}

 

2、需要一个切面

怎么实现无所谓,就是为了生成代理对象,重现问题。

package com.sishuok;

public class Aspect {

    public void before() {
        System.out.println("==before");
    }
}

 

3、 配置文件

    <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。

 

4、测试类

 

测试类很简单,只需要加载配置文件即可。

@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、知道自己使用的是啥编程风格:

  • 先定义接口,然后实现;如UserController---->UserService(接口 其实现是UserServiceImpl),这种情况大多数人都使用接口注入即可
  • 我喜欢直接定义实现,如UserController--->UserService(实现),因为这是一个模块内部的操作,干嘛定义接口呢?可扩展?想想自己扩展过吗?如果实在想要可扩展我一般是这样:UserApi UserApiImpl 可参考我的es脚手架

 

2、知道自己使用的啥代理:

  • JDK动态代理 还是 CGLIB代理, 做到心中有数,尽量别混用。当然最保险的方式就是使用CGLIB代理。

 

明确自己的风格,从一而终,不要为了玩玩都用上,Spring已经很庞大且复杂了,,使用Spring出问题最多的就是AOP部分,遇到AOP问题。可参考《请不要再使用低级别的AOP API

 

 

我喜欢

  • 给自己使用的无需定义接口;即一个模块内部的都是封装的,定义接口并不会得到很多好处,变过几次实现?? “优先面向接口编程,而非实现” 不是必须,是优先;
  • 给朋友(第三方)使用的定义接口;即要公开的功能,因为接口就是个契约,就是沟通用的;
  • 优先使用setter注入,除非必要才使用构造器注入;
  • 使用CGLIB代理,这样基本不会出现AOP代理注入不了或一些隐晦的问题;
  • 优先使用Spring提供的XML标签简化功能定义,如<aop:config>、<task:executor>等,而不要使用低层次API;
  • 尽量使用XML风格的事务,而不是注解风格;
  • 按照配置的内容分多配置文件存放配置,不要一股脑的放在一起,就像不分包那样;
  • 可配置部分(如db数据)还是放到XML中,不要什么都注解;
  • 使用Spring profile 或 maven profile分环境测试(如开发环境、测试环境、正式机环境);

官方文档还是要看的,当然刚开始可能比较困难,但是坚持几次以后就轻松了,出问题先看文档,接着翻javadoc,基本能搞定,当然读一读源码对日常开发的调错还是很有帮助的。

 

27
6
分享到:
评论
43 楼 小董董 2014-03-29  
"我喜欢直接定义实现,如UserController--->UserService(实现),因为这是一个模块内部的操作,干嘛定义接口呢?可扩展?想想自己扩展过吗?"

这个我十分赞同
42 楼 429537044 2014-03-27  
看了很多张老湿的文章,学到了很多,我之前也想过为什么要写那么多接口。
41 楼 jinnianshilongnian 2014-01-25  
chensongIT 写道
      

xiao bai ?
40 楼 chensongIT 2014-01-22  
      
39 楼 ricoyu 2013-10-11  
引用
现在很常见的就是不管如何先定义接口,如下所示:

Java代码  收藏代码
package com.sishuok; 
 
public interface Interface { 
    public void sayHello(); 

然后定义实现,真的有必要吗?思考下。


深有感触!
38 楼 JavaTear2014 2013-07-17  
Test_Wu 写道
除了Spring,您有无类似产品推荐? 国内有吗? Spring太大了,有点不感兴趣了!



有兴趣看看这个,轻量级工具包(总共也不过500k),包含Ioc,orm,event,log,job等,已有项目采用这个工具进行开发的,性能还可以!


Blog:    http://blog.csdn.net/javatear/article/details/8994151
下载地址:http://pan.baidu.com/share/home?uk=2218126399


37 楼 jinnianshilongnian 2013-07-17  
jacking124 写道
我是看着你的博客,渐渐的迷上了Spring!!支持你!!张老湿~~

有用就好,没白浪费我的业余时间 
36 楼 jinnianshilongnian 2013-07-17  
hackee2010 写道
API的设计和Service的设计是两个不同层面的东西。
滥用或者教条主义往往还没搞清楚做的东西是给谁用的,就开始滥用接口、注入之类的东西。

其实我也是不管如何先上接口过来的,但写了这么多年代码发现我写的接口从来没有扩展过, , 以及对一些什么tdd等思想的怀疑,我明白过来,看问题不要太绝对,没有标准答案,而是根据场景选择合适的方案。
35 楼 hackee2010 2013-07-16  
API的设计和Service的设计是两个不同层面的东西。
滥用或者教条主义往往还没搞清楚做的东西是给谁用的,就开始滥用接口、注入之类的东西。
34 楼 evanzzy 2013-07-16  
尤其是对接口的解释,明显是从实践经验中的总结,真的很好,很有同感
33 楼 jacking124 2013-07-16  
我是看着你的博客,渐渐的迷上了Spring!!支持你!!张老湿~~
32 楼 jinnianshilongnian 2013-07-15  
white_crucifix 写道
jinnianshilongnian 写道
white_crucifix 写道
有个更进一步的问题想请教下大家,就是我们的这个接口,即便在“给别人调用”的目的上,是不是也没有必要?

因为别人调用的时候,好像依然无法规避掉与实现类相关的代码,这样是不是不用接口效果也是一样?
求各位大神解惑啊~


1、比如 A需要B,那么A最终要调用B,即A和B之间有耦合,如果B是接口,那么耦合最低,也更容易更换

2、静态代码关系,如


3、如果把Api的实现给A呢? IoC/DI容器就是这个目的。


恩,仔细看了三点,加深了些理解。其实想想我的困惑就是你说的那句话“想想我们自己扩展过吗?”,java web上的action service dao层再很大程度上,如果真的要扩展,在设计上很可能会定义新的接口,换句话说,大部分接口和实现类是一一对应的。所以不用接口我觉得问题应该不大。这个算是拙见哈,毕竟我见到的web系统不多,搞来搞去就这么回事。

另外,第三点“如果”应该是“如何”吧,哈哈,看的时候费了点脑力~


这个真不好意思,写错了 。

引用
换句话说,大部分接口和实现类是一一对应的。所以不用接口我觉得问题应该不大。这个算是拙见哈,毕竟我见到的web系统不多,搞来搞去就这么回事。
这就是常见的企业级应用中的crud部分,如果把这部分也当作API暴露出去,这是一个很不好的设计,如果其他模块需要使用这个模块,可以封装一个如***API的接口,按需暴露接口、提供更好的API(比如名字等)
31 楼 white_crucifix 2013-07-15  
jinnianshilongnian 写道
white_crucifix 写道
有个更进一步的问题想请教下大家,就是我们的这个接口,即便在“给别人调用”的目的上,是不是也没有必要?

因为别人调用的时候,好像依然无法规避掉与实现类相关的代码,这样是不是不用接口效果也是一样?
求各位大神解惑啊~


1、比如 A需要B,那么A最终要调用B,即A和B之间有耦合,如果B是接口,那么耦合最低,也更容易更换

2、静态代码关系,如


3、如果把Api的实现给A呢? IoC/DI容器就是这个目的。


恩,仔细看了三点,加深了些理解。其实想想我的困惑就是你说的那句话“想想我们自己扩展过吗?”,java web上的action service dao层再很大程度上,如果真的要扩展,在设计上很可能会定义新的接口,换句话说,大部分接口和实现类是一一对应的。所以不用接口我觉得问题应该不大。这个算是拙见哈,毕竟我见到的web系统不多,搞来搞去就这么回事。

另外,第三点“如果”应该是“如何”吧,哈哈,看的时候费了点脑力~
30 楼 jinnianshilongnian 2013-07-15  
Test_Wu 写道
除了Spring,您有无类似产品推荐? 国内有吗? Spring太大了,有点不感兴趣了!

暂时还没啥研究,希望其他朋友推荐下。
29 楼 jinnianshilongnian 2013-07-15  
Test_Wu 写道
过分谦虚==骄傲!!

哈哈,事实就是事实,没什么谦虚的,也没什么骄傲的。不喜欢扣帽子
28 楼 Test_Wu 2013-07-15  
除了Spring,您有无类似产品推荐? 国内有吗? Spring太大了,有点不感兴趣了!
27 楼 Test_Wu 2013-07-15  
过分谦虚==骄傲!!
26 楼 jinnianshilongnian 2013-07-15  
Test_Wu 写道
楼主写了很多关于Spring的文章,水平非常精湛! 您水平如此之高,何不造一个新轮子,吸收Spring精华,去其弊端呢?

看过很多文章都在说Spring是如何如何好! 我今天向楼主了解一下:那Spring有缺陷吗? 是哪些呢? 谢谢了!



我水平一般,我也还处于学习阶段,还造不起轮子。我觉得spring足够好,如果说缺点就是越来越庞大而且太灵活了。
1、庞大:不过现在spring分模块分的挺好的,但是太多模块,造成不知道哪个模块是必须的,哪个是可选的,但是这个问题可以通过学习解决。
2、灵活的让我不知道到底使用哪种方式去开发,如本篇及以前提到的。但这不是spring的问题,而是开发人员的问题,既然选择了一个框架开发,那么就需要对一些核心的概念系统学习,而不是似是而非,我之前提到的很多问题都是这个造成的。
3、关于造轮子:我现在也还在学习阶段,而且我觉得使用目前的框架也很顺手,只需要自己加点扩展就能很好的并简单的完成工作,所以我现在认为我没必要造轮子。

我认为只有足够理解了某个框架,才能足够好的使用这个框架,才能发现这个框架的问题。

我现在还处于理解阶段,欢迎探讨
25 楼 Test_Wu 2013-07-15  
楼主写了很多关于Spring的文章,水平非常精湛! 您水平如此之高,何不造一个新轮子,吸收Spring精华,去其弊端呢?

看过很多文章都在说Spring是如何如何好! 我今天向楼主了解一下:那Spring有缺陷吗? 是哪些呢? 谢谢了!


24 楼 jinnianshilongnian 2013-07-15  
alvin198761 写道
写个helloword都要用spring了,岂不是又要几十kb?这个时代真神奇,框架组件离我越来越远了,什么都是自己实现,看看用框架的,真心伤不起


1、我这个是从一个朋友那的真实项目中抽取出来的,尽量简化 方便读者阅读

2、此处只是就事论事,不讨论自己实现神马框架;

3、不管自己写的,还是用别人的,不都是在用框架吗? 非得用自己写的、或者去框架化? 真心伤不起

相关推荐

    反思中国我国古代婚姻制度.doc

    中国古代婚姻制度其实是“一夫一妻多妾”制,在中国封建社会,妇女没有社会地位,夫为妻纲,妇女的一切只能服从和依赖其丈夫,从一而终。一个男人一般只有一个正妻,却有多个妾,同时男人娶几个女人都不受法律和道德...

    近况作文700字_高中高三作文,-,58作文

    首先,作者描述了自己的近况,表现为一种颓废的状态,连续旷课,沉溺于回忆过去。这可能源于一段未解决的感情问题,使作者陷入了深深的思考。这种行为在青少年时期并不罕见,特别是在面对情感困扰时,人们往往会选择...

    爱情是什么.doc

    另一方面,幽默的回答指出,爱情有时可能是一种冲动,一种两个人共同的追求。它可以是短暂的激情,也可以是长久的陪伴。爱情可能会让人感到兴奋,也可能变得平淡,但它始终是我们生活中不可或缺的一部分,超越了外在...

    竞品分析 智联招聘、Boss直聘使用报告.pdf

    5. 招聘市场的未来:由于跳槽意愿增加,招聘市场可能会逐渐演变成一个高频次的市场,而不是父母辈那种从一而终的职业生涯。在使用频次、使用人数上呈现增长趋势。所以对招聘市场的未来是一个利好。 6. 招聘App的...

    PostMan接口调试工具.rar

    PostMan是一款广受欢迎的API(应用程序编程接口)测试和调试工具,尤其对于Web开发者和测试工程师来说,它是一个不可或缺的工具。它最初是一款Chrome浏览器扩展,但现在已经发展为一个独立的应用程序,支持Windows、...

    详解C++中指针和引用的区别

    Reference作为一个变量AA的别名,在它的整个生命周期内,它只能“从一而终”,始终是第一次初始化它的那个变量的别名,在这期间任何对它的操作,都等同于对变量AA的操作。 通过例子我们可以看到,Pointer可以随时...

    深入解析C++中的引用类型

    在C++编程语言中,引用是一种特殊的类型,它不是变量,也不是指针,而是对已存在对象的另一种访问方式。引用一旦被初始化为某个对象,它就永久地绑定到那个对象上,不能改变引用的目标。这种特性使得引用在很多场合...

    天津市静海县第四中学2020学年高二语文下学期第三次月考试题.doc

    9. 标点符号运用:标点符号的正确使用是书面表达的规范之一,如逗号、句号、引号等的使用,对于句子结构的划分和语义的理解有直接影响。 综上所述,这些题目涉及了语文学习的基础知识,包括字音、字形、词语搭配、...

    C++中引用与指针的区别(详细介绍)

    指向不同类型的指针的区别在于指针类型可以知道编译器解释某个特定地址(指针指向的地址)中的内存内容及大小,而void*指针则只表示一个内存地址,编译器不能通过该指针所指向对象的类型和大小,因此想要通过void*...

    安徽省利辛县2017届九年级上学期第一次月考试题(语文).doc

    同时,文中涉及到词语的拼音、成语的正确书写及词义的应用,如“视频”、“出糗”、“募捐”等词的注音,“衰竭”的正确写法以及“从一而终”在语境中的不恰当使用。 3. 中国古典文学:《水浒传》是中国四大名著之...

    C++引用和指针的区别,C++虚函数原理,C++面试经验

    C++ 引用和指针是两种不同的概念。虽然它们都可以用来表示内存地址,但是它们有着不同的特点和应用场景。 1. 相同点:引用和指针都是地址的概念,指针指向一块内存,它的内容是所指内存的地址;引用是某块内存的...

    2020年高中语文第2课祝福教案3新人教版必修3

    7. **集体无意识**:鲁四老爷代表的“干净”标准,实际上是一种集体无意识的表现,反映出封建社会对女性的刻板印象和不公待遇。祥林嫂被视为“不干净”,是因为她不符合传统道德规范,这种观念体现了旧社会的偏见和...

    当前执行力建设中存在的问题.doc

    把简单重复上级文件和讲话精神看作是贯彻执行,只讲执行的形式,不讲执行的结果,根本达不到贯彻落实的目的。或者脱离本地、本单位的实际情况,教条式的执行。不带头做表率,不深入工作调查研究,做事草率马虎,热...

    民国初年婚姻观念的变革.docx

    **贞操观的新解**:一些知识分子提出,贞操应当是一种双方共同承担的责任,而不是单方面强加给女性的道德约束。这种观点是对传统贞节观念的重大挑战。 **反对封建贞操观**:在《新青年》杂志上,围绕“贞操问题”...

    2019年大学生婚恋观调查报告参考.doc

    虚荣型的大学生由于只追求一时的感情满足和快乐,缺乏明确的爱情基础和目标,极易破裂。 大学生的迷茫成年话题 根据相关调查,大学生中有高达87.9%的人在校期间谈过恋爱,其中沿海地区高达94.6%。但是,大学生恋爱...

    c++中指针和引用的区别

    在 C++ 编程语言中,指针和引用是两个常用的概念,但是初学者容易混淆它们二者之间的区别。在本文中,我们将从概念、函数参数传递和编译角度来阐述指针和引用的区别。 概念上,指针是一个变量,它存放的是变量的...

    初中语文文学讨论现当代文学橡树下唱歌的鸢尾花__舒婷

    在舒婷的另一首诗《神女峰》中,她对神女峰这一传统女性贞洁象征进行了重新解读,提出对女性从一而终的封建观念的质疑。通过对神女峰的现代诠释,舒婷鼓励女性追求真实的感情和个体自由,而非被束缚于古老的道德规范...

    c++中引用和指针的区别和联系

    C++中的引用和指针是两种重要的编程工具,它们在某些方面有相似之处,但在其他方面又有明显的区别。引用和指针都是地址的概念,都可以用来间接访问内存中的数据。然而,它们在使用和行为上存在本质的不同。 首先,...

    Cheers快樂工作人 [第221期]_好工作入手.pdf

    另一方面,未来的职场可能将出现两种货币:机器币和人类币。机器币用于购买机器生产的产品和服务,而人类币则用于购买人类独有的资源和创造力。这种划分说明了为什么人类的创造力、服务意识和合作能力变得越来越重要...

Global site tag (gtag.js) - Google Analytics