刚开始接触这个概念的时候感觉依赖注入好神秘,尤其是看到资料说某个大学教授关于这个东西发表了一篇论文,然后开源社区就是根据这篇论文逐渐的形成了著名的Spring框架,什么控制反转等概念顿时风靡了开源社区。这使得EJB这个JavaEE亲妈的儿子都不招待见了(当时还是EJB2)。
起初是怀着崇敬的心态去学习Spring感觉这个框架配置好灵活,因为好灵活所以好麻烦,因为好麻烦所以好高深。后来越用越感觉没啥了,说到底就是给一个属性赋值而已,至于什么框架管理Bean说白了就是通过反射去控制Bean的生成(关于Spring不是本文的重点)。最近在解决ESB的几个Bug的时候顿时感觉依赖注入没那么简单。
项目中关于ESB的实现用的是开源的Mule,众所周知,ESB的核心理念就是消息格式转换以及消息路由,所以各种协议各种支持,各种消息各种分发。今天要说的就是通过Spring的注入改造Mule对SFTP消息的定制。
(从2005年发表1.0版本以来,Mule吸引了越来越多的关注者,已成为开源ESB中的一支独秀)
在Mule的原始SFTP支持当中,客户端通过SFTP协议去远程的目录下抓取文件,但是这个抓取的过程是很简单的,一次随机抓取一个文件,直到远程目录中再没有合适的文件可以抓为止。但是这种拙劣的实现方式远远不能满足用户的需要(这个用户其实就是我啦),但是通过查看源码以及官方文档等手段最终得到了下面的答案,原来Mule当中的Bean是可以通过spring灵活注入的,也就是说如果你感觉Mule当中的哪个Bean实现的不满意大可以自己写一个。你要做的就是将这个Bean当做其调用者的一个属性注入进去就可以了。核心代码如下(贴代码是最苍白的表达手法):
<sftp:connector name="incoming-mandate-connector" archiveDir="${esb.archive.path}/mandate/incoming" useTempFileTimestampSuffix="true" autoDelete="true" identityFile="${esb.autogiro.mandate.incoming.sftp.identityFile}" passphrase="${esb.autogiro.mandate.incoming.sftp.passphrase}" sizeCheckWaitTime="${esb.autogiro.mandate.incoming.sftp.sizeCheckWaitTime}"> <spring:property name="serviceOverrides"> <spring:map> <spring:entry key="requester.factory" value="se.leandev.lfp.esb.autogiro.OrderFilesSftpMessageRequesterFactory"/> </spring:map> </spring:property> </sftp:connector>
问题解决了是解决了,但和以往一样,解决问题仅仅是一个开始。要思考整个过程当中我们学到了什么,面向接口编程?依赖注入?控制反转(其实控制反转包括依赖注入,网上很多人写了很多文章指出两者不同,笔者认为哪些人和笔者一样都是吃的太饱了)?不对这些都不是自己想要的答案,这个答案要更抽象,更具有代表性才行。对!就是这个词语,“抽象”!
一个能解决问题的人是普通人,一个能解决一系列问题的人才是高人,一个能解决所有问题的……丫的这货根本不是人。也就是说将公共的部分提取出来进行抽象是保证在原有系统架构不变的基础上满足更多变态需求的根本。换句不绕口的话就是,把主要矛盾摆在那里,允许不同的人采用不同的解决办法解决。
最后再来说说接口吧,在平时的开发过程当中我们很可能感觉写个接口没什么用处,麻烦、浪费时间,还不如直接拿类来用得好(不得不说的我们平时的确也是这么干的),等到某一天这个功能需要特殊定制了才发现原来要是用接口该多么方便。造成以上后果的原因在于我们对接口的设计不够抽象,以往那种接口几个方法实现类几个方法的编程方式可以说是最拙劣(注意这里没有之一)的代码实现方式,真正好的框架或者说产品是应该将接口抽象然后让后来者去灵活实现的。嗨,JavaEE规范不就是这么做的么,说了一圈说回来了。