Spring+hibernate实战(二)

项目很小,主体部分也完成的差不多了,但麻雀虽小,五脏具全,我在其中用到了springIoCtransaction管理,也用到了简单的AOP功能,同时使用了spring mvc,下面我对它们做一些总结,也跟和我一样刚刚踏入spring大门的兄弟们探讨探讨:

(一)spring IoC探讨

先还是谈谈spring IoC的使用。IoC也就是控制反转,即由容器来调用你的代码,而你不用去使用容器的接口,一般都用好莱坞原则来进行形象的比喻。最近在看那本without EJB才知道其实DI(依赖注入)其实只是IoC的一种实现,而DI又分为set注入和constructor注入。更轻量级的IoC容器PicoContainer就是采用constructor注入,spring两种都支持,但Rod Johnson经过详细的比较,建议还是一般采用set注入方式。理解set注入,对使用和深入了解spring框架非常重要。

为了做到面向接口编程,我们总是尽量使用接口声明,但接口是不能new的,如果不使用IoC容器,终归需要个地方new它的实现类。如Interface a=new InterfaceImpl(),这样还是在代码中形成了对实现类的依赖。当然我们可以使用factory模式来将声明提取到工厂类中,但这样又形成了对工厂的依赖,而且工厂也会越来越多,不便于管理。于是我们通过配置如

 

<bean id="emailAdvisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">

这样在配置文件中声明其实现类,就消除了对具体实现类的耦合。而一个类通常需要放置其它类的引用,或者使用从其它配置文件读出的值,这个时候就是set注入显示威力的时候了。

<bean id="msg" class="org.springframework.mail.SimpleMailMessage">

       
<property name="from" value="${mail.from}" />

    bean>这是声明一个Message对象实例的配置文件,${mail.from}表明是在*.properties文件配置的值,看到这个我们就知道SimpleMailMessage是一个具体类,有一个from的属性,同时有一个setFrom的公共方法。SpringContextLoader在启动时就会自动创建一个SimpleMailMessage对象的实例,并将mail.from对应的值用set方法注入进去,spring默认会创建Singleton对象。以后碰到需要配置的什么参数,就可以采用这种方式注入,注意.properties文件还是分个类较好,如jdbc.properties配置数据库访问参数,mail.properties配置邮件参数(我这也是学的jpetstore的)。

以下配置就是将一个mailSender和一个msg引用注入到一个emailAdvice中去。emailAdvice使用的是他们的接口声明,然后加上set方法,而不关心它们是用什么实现类。

<bean id="emailAdvice" class="com.bankcomm.vpn.service.SendMailAdvice">

       
<property name="mailSender" ref="mailSender" />

       
<property name="msg" ref="msg" />

</bean
>

讲一个巧妙使用spring set注入解决实际问题的例子。系统要求某些用户有审批的权限,通常我们使用数据库,但由于是小项目,能审批的用户也不多,我又不想写什么Dao,于是希望能在配置文件中直接定义。如果不使用spring,在以往项目中的做法就是定义一个xml文件,然后写方法去解析文件,把配置的用户读取到一个config类中,这个过程又必须在系统启动时进行,所以有个StarterServlet,在启动后调用这个方法,StarterServlet又需要定义在web.xml中。是不是很复杂?

有了spring,我们就有了新的选择。先看下面的配置文件:

      

<bean id="auditer" class="com.bankcomm.vpn.service.Auditer">

           
<property name="auditers">

              
<list>

                  
<value>info1value>

                
<value>info2value>

                 

              
</list>

           
</property>

       
</bean>

为简单起见,我没有使用接口,直接定义了一个Auditer类,它有一个List类型的auditers属性,然后加个set方法。对auditers里面的值,就使用spring支持的list配置方式进行注入。你可以配多个valuecontextLoader启动时就会自动把这些value填入一个ArrayList实现,然后setauditer类中,你就可以直接使用这个类了。你看,是不是很方便就实现了这个功能,这也从一个方面体现了spring的强大之处。

(二)spring transaction管理探讨

说到transaction管理,其实我也没有太多经验(项目经验太少!),以前写jdbc代码,就是使用setAutoCommit(false)来实现,要用到JTA来实现跨数据库的情况还没碰到过。所以这里就简单讲讲如何写spring配置文件来支持transaction的声明式配置。

<bean id="baseTransactionProxy" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"

         
abstract="true">

       
<property name="transactionManager" ref="transactionManager"/>

       
<property name="transactionAttributes">

           
<props>

              
<prop key="insert*">PROPAGATION_REQUIRED</prop>

              
<prop key="update*">PROPAGATION_REQUIRED</prop>

              
<prop key="*">PROPAGATION_REQUIRED,readOnlyprop>

           
</props>

       
</property>

    
</bean>

以上配置文件就是定义了一个baseTransactionProxy 对象,它注入一个transactionManager对象,并注入一个transactionAttributesProperties对象,这个Properties对象的配置就是内配置的内容。transactionManager可以根据你的需要来进行配置,如使用hibernate,可以用

<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager"><property name="sessionFactory" ref="sessionFactory"/></bean>

来配置。如果使用JTA就使用

<bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager"/>

这里很方便就能切换到另一种transactionManager的实现上去。PROPAGATION_REQUIRED表明会放入当前的事务中,如果没有就创建一个。Readonly表明此方法只读,能提高速度,spring还支持隔离级别的配置,具体配置说明,可以看springapi文档http://www.springframework.org/docs/api/org/springframework/transaction/TransactionDefinition.html

有了这个baseTransactionProxy,我们就可以用下面的配置使service层的Façade对象具备事务管理功能了。这里VpnImpl 为一个Façade接口的实现类,它实现对Dao层的代理然后,提供对外的统一接口。好处就是只有一个接口类,对transaction的配置和其它AOP配置都可以针对这个Façade进行,希望详细了解Façade模式可以参看模式相关书籍。

<bean id="vpn" parent="baseTransactionProxy">

       
<property name="target">

           
<bean class="com.bankcomm.vpn.service.VpnImpl">

              
<property name="userDao" ref="userDao" />

              
<property name="submitVpnRequest" ref="submitVpnRequest" />

           
</bean>

       
</property>

       
<property name="postInterceptors">

           
<list>

              
<ref bean="emailAdvisor" />

           
</list>

       
</property>

    
</bean>

有了springtransaction管理,声明式事务就不再是EJB所独有了,我们可以使用spring的事务,而避免仅仅因为要声明式事务而使用EJB这样重量级的东西了。

       先写到这里吧,下篇我再继续AOPspring mvc的讨论。

posted on 2005-11-07 16:02 pesome 阅读(2473) 评论(0)  编辑  收藏 所属分类: Spring+Struts+Hibernate


只有注册用户登录后才能发表评论。


网站导航:
 
<2005年11月>
303112345
6789101112
13141516171819
20212223242526
27282930123
45678910

导航

统计

公告

主要记录作者在学习java中的每一步足迹。除非特别说明,所有文章均为本blog作者原创,如需转载请注明出处和原作者,如用于商业目的,需跟作者本人联系。
欢迎大家访问:

常用链接

留言簿(16)

随笔分类

随笔档案

文章分类

文章档案

相册

收藏夹

java技术

人间百态

朋友们的blog

搜索

最新评论

阅读排行榜

评论排行榜