您的位置:首页 > 编程语言 > ASP

Spring.Net+NHibenate+Asp.Net mvc +ExtJs 系列 4 ----业务逻辑层

2008-11-18 14:57 603 查看
上一次我们完成了数据访问层的接口和实现,这次我们按部就班的完成业务层接口及实现,并采用spring.net声明式事务.另外,采用nunit对业务实现进行单元测试.
象petshop框架一样,我们先定义业务层接口,这里只和实体有有耦合.我们拿用户User为例:





IUserManager
using DirectCenter.Model;

namespace DirectCenter.IBLL
{
    /// <summary>
    /// 用户管理
    /// </summary>
    public interface IUserManager
    {
        /// <summary>
        /// 创建一个用户(返回包含默认值)
        /// </summary>
        /// <returns></returns>
        User NewUser();

        /// <summary>
        /// 保存用户
        /// </summary>
        /// <param name="user">用户实体</param>
        /// <returns></returns>
        User SaveUser(User user);

        /// <summary>
        /// 获取用户
        /// </summary>
        /// <param name="userId">用户ID</param>
        /// <returns></returns>
        User GetUser(string userId);

        /// <summary>
        /// 删除用户
        /// </summary>
        /// <param name="userId">用户ID</param>
        /// <returns></returns>
        void  DeleteUser(string userId);

        /// <summary>
        /// 更新用户
        /// </summary>
        /// <param name="user">用户实体</param>
        /// <returns></returns>
        User UpdateUser(User user);
    }
}



同理,这里也是简单使出了几个通常的增删改查的接口,其它的业务接口我们在接下来的前台实现中,再来添加.


在业务层的具体实现中,我们用了数据访问接口IUserDao属性,通过Ioc注入具体的数据访问实现,同样,如果我们这里需要在这里使用其它的业务类的时候,同样也通过IOC的方式.不过这样很有可能造成循环依赖.(这里有一个解决方法http://www.blogjava.net/alwayscy/archive/2008/02/24/181726.html)




UserManager
#region Imports

using System;
using System.Collections;
using System.Text;

using DirectCenter.IBLL;
using DirectCenter.IDAL;
using DirectCenter.Model;

#endregion

namespace DirectCenter.BLL
{
    public class UserManager:IUserManager
    {
        #region Properties

        public IUserDao UserDao { get; set; }

        #endregion

        /// <summary>
        /// 创建一个用户(返回包含默认值)
        /// </summary>
        /// <returns></returns>
        public User NewUser()
        {
            var user = new User();

            //可以采用系统配置
            user.CreateTime = DateTime.Now;

            user.ValidFrom = DateTime.Now;
            user.ValidTo = Convert.ToDateTime("2999-12-31");
            return user;
        }

        /// <summary>
        /// 保存用户
        /// </summary>
        /// <param name="user">用户实体</param>
        /// <returns></returns>
        public User  SaveUser(User user)
        {
            Validate(user);
            if (GetUser(user.UserID) != null)
                throw new  Exception("已经存在的用户");
            return  UserDao.Save(user);
        }

        /// <summary>
        /// 获取用户
        /// </summary>
        /// <param name="userId">用户ID</param>
        /// <returns></returns>
        public User GetUser(string userId)
        {
            return UserDao.FindById(userId);
        }

        /// <summary>
        /// 删除用户
        /// </summary>
        /// <param name="userId">用户ID</param>
        /// <returns></returns>
        public void   DeleteUser(string userId)
        {
            var user = new User();
            user.UserID = userId;

            UserDao.Delete(user);
        }

        /// <summary>
        /// 更新用户
        /// </summary>
        /// <param name="user">用户实体</param>
        /// <returns></returns>
        public User  UpdateUser(User user)
        {
            return UserDao.SaveOrUpdate(user);
        }

        private void Validate(User  user)
        {
            //TODO throw exception on error.
        }
    }
}
接下来的注入工作和声明式事务都在配制文件中完成,为DirectCenter.App项目添加Services.xml文件(不要忘了嵌入式资源).首先先注入Dao对象:




UserManager
 <object id="UserManager" type="DirectCenter.BLL.UserManager,DirectCenter.BLL">
        <property name="UserDao" ref="UserDao"/>
    </object>

UserDao这个对象在上一次的Dao.xml中已经定义过了.
接下来我们来实现声明式事务,在Services.xml中添加:





transactionManager
    <object id="transactionManager"
          type="Spring.Data.NHibernate.HibernateTransactionManager, Spring.Data.NHibernate20">
        <property name="DbProvider" ref="DbProvider"/>
        <property name="SessionFactory" ref="NHibernateSessionFactory"/>
    </object>

    <object id="TransactionInterceptor" type="Spring.Transaction.Interceptor.TransactionInterceptor, Spring.Data">
        <property name="TransactionManager" ref="transactionManager"/>
        <property name="TransactionAttributeSource">
            <object type="Spring.Transaction.Interceptor.AttributesTransactionAttributeSource, Spring.Data"/>
        </property>
    </object>
    
    
    <object id="BaseTransactionManager"  type="Spring.Transaction.Interceptor.TransactionProxyFactoryObject" abstract="true">
        <property name="PlatformTransactionManager" ref="transactionManager"/>
        <property name="TransactionAttributes">
            <name-values>
                <add key="Save*" value="PROPAGATION_REQUIRED"/>
                <add key="Set*" value="PROPAGATION_REQUIRED"/>
                <add key="Finish*" value="PROPAGATION_REQUIRED"/>
                <add key="Update*" value="PROPAGATION_REQUIRED"/>
                <add key="Delete*" value="PROPAGATION_REQUIRED"/>
                <add key="Add*" value="PROPAGATION_REQUIRED"/>
                <add key="Get*" value="PROPAGATION_REQUIRED,readOnly"/>
                <add key="Find*" value="PROPAGATION_REQUIRED,readOnly"/>
                <add key="Load*" value="PROPAGATION_REQUIRED,readOnly"/>
                <add key="*" value="PROPAGATION_REQUIRED"/>
            </name-values>
        </property>
    </object>



TransactionAttributes中的列出的值表示对对应的方法采用事务,比如对Save开头的方法支持事务.(*是通配符),其中value的值可以有以下几种:
PROPAGATION_REQUIRED--支持当前事务,如果当前没有事务,就新建一个事务。这是最常见的选择。
PROPAGATION_SUPPORTS--支持当前事务,如果当前没有事务,就以非事务方式执行。
PROPAGATION_MANDATORY--支持当前事务,如果当前没有事务,就抛出异常。
PROPAGATION_REQUIRES_NEW--新建事务,如果当前存在事务,把当前事务挂起。
PROPAGATION_NOT_SUPPORTED--以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
PROPAGATION_NEVER--以非事务方式执行,如果当前存在事务,则抛出异常。
PROPAGATION_NESTED--如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则进行与PROPAGATION_REQUIRED类似的操作.
readOnly表示此方法只读的,不能够修改数据

关于声明式事务的一些细节在下面的两个文章中可以了解详细些:
http://javabrain.javaeye.com/blog/106391
http://caterpillar.onlyfun.net/GossipCN/SpringGossip/TransactionAttributeSource.html

接着,我们再添加采用了事务的业务对象,继承于我们声明的事务基类.





UserManagerTrans
   <object id="UserManagerTrans" parent="BaseTransactionManager">
        <property name="Target" ref="UserManager"/>
    </object>


这样就完成了业务部分,让我们测试一下吧.首先添加Services.xml到objects.xml中.接下来就添加UserManagerTest.cs来完成对用户保存的测试:





UserManagerTest.cs
using System;

using NUnit.Framework;
using Spring.Testing.NUnit;
using DirectCenter.Model;
using DirectCenter.IBLL;

namespace DirectCenter.UnitTest
{
    [TestFixture]
    public  class UserManagerTest :AbstractTransactionalDbProviderSpringContextTests
    {
        protected override string[] ConfigLocations
        {
            get
            {
                return new String[] { "objects.xml" };
            }
        }
        protected IUserManager UserManager
        {
            get
            {
                return applicationContext.GetObject("UserManagerTrans") as IUserManager;
            }
        }

        [Test]
        public void SaveUserTest()
        {
            User user = UserManager.NewUser();
            user.UserID = "buyer0p";
            user.Password = "admin";
            user.UserName = "刘翔";
            UserManager.SaveUser(user);
            transactionManager.Commit(transactionStatus);
        }
    }
}

采用声明式事务的好处就是把事务的操作和数据访问的限制从具体的业务层中解耦出来,在实际写业务层的时候,不用关心事务的操作,同样,在这里也可以采用aop的方式实现日志,异常,权限.
本次代码下载
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: