應用分層的迷惑
WebService及DAO三層劃分就像西方國家的立法行政司法三權分立一樣被奉為金科玉律甚至有開發人員認為如果要使用Spring事務管理就一定先要進行三層的劃分這個看似荒唐的論調在開發人員中頗有市場更有甚者認為每層必須先定義一個接口然後再定義一個實現類其結果是一個很簡單的功能也至少需要個接口個類再加上視圖層的JSP和JS等打牌都可以轉上兩桌了這種誤解贻害不淺
對將面向接口編程奉為圭臬認為放之四海而皆准的論調筆者深不以為然是的面向接口編程是MartinFowlerRodJohnson這些大師提倡的行事原則如果拿這條原則去開發架構開發產品怎麼強調都不為過但是對於我們一般的開發人員來說做的最多的是普通工程項目往往最多的只是一些對數據庫增刪查改的功能此時面向接口編程除了帶來更多的類文件外看不到更多其它的好處
Spring框架提供的所有附加的好處(AOP注解增強注解MVC等)唯一的前提就是讓POJO的類變成一個受Spring容器管理的Bean除此以外沒有其它任何的要求下面的實例用一個POJO完成所有的功能既是Controller又是Service還是DAO
清單MixLayerUserServicejava
packageusermixlayer;
importorgspringframeworkbeansfactoryannotationAutowired;
importorgsprireJdbcTemplate;
importorgspringframeworkstereotypeController;
importorgspringframeworkwebbindannotationRequestMapping;
//①將POJO類通過注解變成SpringMVC的Controller
@Controller
publicclassMixLayerUserService{
//②自動注入JdbcTemplate
@Autowired
privateJdbcTemplatejdbcTemplate;
//③通過SpringMVC注解映URL請求
@RequestMapping(/logondo)
publicStringlogon(StringuserNameStringpassword){
if(isRightUser(userNamepassword)){
Stringsql=UPDATEt_useruSETuscore=uscore+?WHEREuser_name=?;
jdbcTemplateupdate(sqluserName);
returnsuccess;
}else{
returnfail;
}
}
privatebooleanisRightUser(StringuserNameStringpassword){
//dosth
returntrue;
}
}
通過@Controller注解將MixLayerUserService變成Web層的Controller同時也是Service層的服務類此外由於直接使用JdbcTemplate訪問數據所以MixLayerUserService還是一個DAO來看一下對應的Spring配置文件
清單applicationContextxml
<?xmlversionxmlversion=encoding=UTF?>
<beansxmlnsbeansxmlns=
xmlns:xsi=instance
xmlns:context=
xmlns:p=
xmlns:aop=
xmlns:tx=
xsi:schemaLocation=
beansxsd
contextxsd
aopxsd
txxsd>
<context:componentscanbasepackagecontext:componentscanbasepackage=usermixlayer/>
<beanclassbeanclass=orgspringframeworkwebservletmvcannotation
AnnotationMethodHandlerAdapter/>
<beanclassbeanclass=orgspringframeworkwebservletview
InternalResourceViewResolver
pp:prefix=/WEBINF/jsp/p:suffix=jsp/>
<beanidbeanid=dataSource
class=monsdbcpBasicDataSource
destroymethod=close
p:driverClassName=oraclejdbcdriverOracleDriver
p:url=jdbc:oracle:thin:@localhost::orcl
p:username=test
p:password=test/>
<beanidbeanid=jdbcTemplate
class=orgsprireJdbcTemplate
p:dataSourceref=dataSource/>
<beanidbeanid=jdbcManager
class=orgspringframeworkjdbcdatasourceDataSourceTransactionManager
p:dataSourceref=dataSource/>
<aop:configproxytargetclassaop:configproxytargetclass=true>
<aop:pointcutidaop:pointcutid=serviceJdbcMethod
expression=execution(public*usermixlayerMixLayerUserService*())/>
<aop:advisorpointcutrefaop:advisorpointcutref=serviceJdbcMethod
adviceref=jdbcAdviceorder=/>
</< span>aop:config>
<tx:adviceidtx:adviceid=jdbcAdvicetransactionmanager=jdbcManager>
<tx:attributes>
<tx:methodnametx:methodname=*/>
</< span>tx:attributes>
</< span>tx:advice>
</< span>beans>
在①處我們定義配置了AnnotationMethodHandlerAdapter以便啟用SpringMVC的注解驅動功能而②和③處通過Spring的aop及tx命名空間以及Aspject的切點表達式語法進行事務增強的定義對MixLayerUserService的所有公有方法進行事務增強要使程序能夠運行起來還必須進行webxml的相關配置
清單webxml
<?xmlversionxmlversion=encoding=GB?>
<webappversionwebappversion=xmlns=
xmlns:xsi=instance
xsi:schemaLocation=
app__xsd>
<contextparam>
<paramname>contextConfigLocation</< span>paramname>
<paramvalue>classpath*:user/mixlayer/applicationContextxml</< span>paramvalue>
</< span>contextparam>
<contextparam>
<paramname>logjConfigLocation</< span>paramname>
<paramvalue>/WEBINF/classes/logjproperties</< span>paramvalue>
</< span>contextparam>
<listener>
<listenerclass>
springframeworkwebutilLogjConfigListener
</< span>listenerclass>
</< span>listener>
<listener>
<listenerclass>
sprntextContextLoaderListener
</< span>listenerclass>
</< span>listener>
<servlet>
<servletname>user</< span>servletname>
<servletclass>
springframeworkwebservletDispatcherServlet
</< span>servletclass>
<initparam>
<paramname>contextConfigLocation</< span>paramname>
<paramvalue>classpath:user/mixlayer/applicationContextxml</< span>paramvalue>
</< span>initparam>
<loadonstartup></< span>loadonstartup>
</< span>servlet>
<servletmapping>
<servletname>user</< span>servletname>
<urlpattern>*do</< span>urlpattern>
</< span>servletmapping>
</< span>webapp>
這個配置文件很簡單唯一需要注意的是DispatcherServlet的配置默認情況下SpringMVC根據Servlet的名字查找WEBINF下的servletxml作為SpringMVC的配置文件在此我們通過contextConfigLocation參數顯式指定SpringMVC配置文件的確切位置
將orgspringframeworkjdbc及orgspringframeworktransaction的日志級別設置為DEBUG啟動項目並訪問應用MixLayerUserService#logon方法將作出響應查看後台輸出日志
清單執行日志
::DEBUG(AbstractPlatformTransactionManagerjava:)
Creatingnewtransactionwithname
[usermixlayerMixLayerUserServicelogon]:PROPAGATION_REQUIREDISOLATION_DEFAULT
::DEBUG(DataSourceTransactionManagerjava:)
AcquiredConnection[monsdbcpPoolableConnection@ecbf]
forJDBCtransaction
::DEBUG(DataSourceTransactionManagerjava:)
SwitchingJDBCConnection
[monsdbcpPoolableConnection@ecbf]tomanualcommit
::DEBUG(JdbcTemplatejava:)
ExecutingpreparedSQLupdate
::DEBUG(JdbcTemplatejava:)
ExecutingpreparedSQLstatement
[UPDATEt_useruSETuscore=uscore+?WHEREuser_name=?]
::DEBUG(JdbcTemplatejava:)
SQLupdateaffectedrows
::DEBUG(AbstractPlatformTransactionManagerjava:)
Initiatingtransactioncommit
::DEBUG(DataSourceTransactionManagerjava:)
CommittingJDBCtransactiononConnection
[monsdbcpPoolableConnection@ecbf]
::DEBUG(DataSourceTransactionManagerjava:)
ReleasingJDBCConnection[monsdbcpPoolableConnection@ecbf]
aftertransaction
::DEBUG(DataSourceUtilsjava:)
ReturningJDBCConnectiontoDataSource
日志中粗體部分說明了MixLayerUserService#logon方法已經正確運行在事務上下文中Spring框架本身不應該是復雜化代碼的理由使用Spring的開發者應該是無拘無束的從實際應用出發去除掉那些所謂原則性的接口去除掉強制分層的束縛簡單才是硬道理
From:http://tw.wingwit.com/Article/program/Java/ky/201311/27924.html