业务规则层设计说明
发布时间:2020-12-17 02:07:21 所属栏目:安全 来源:网络整理
导读:? 一.具体介绍 目的:降低业务逻辑层耦合和进行动态加载提高系统的可扩展性 使用工具: spring.net 框架 通过 IOC 注入机制实现 二.具体机制 面向接口编程,所有的服务都需要提供对外的接口,通过 spring.net 的 IOC 容器进行服务的 组合,通过依赖注入形
?
一.具体介绍
目的:降低业务逻辑层耦合和进行动态加载提高系统的可扩展性
使用工具:
spring.net
框架
通过
IOC
注入机制实现
二.具体机制
面向接口编程,所有的服务都需要提供对外的接口,通过
spring.net
的
IOC
容器进行服务的
组合,通过依赖注入形式将需要的服务进行注入。
新增模块规范描述如下
:
当系统需要添加新服务—
>
首先声明该服务接口—
>
实现该服务接口—
>
将此实例注入到
spring.net IOC
容器—
>
将此服务放入
ServiceContainer
统一进行管理—
>
通过模块容器(服务容器)来对服务进行调用,也可以通过构造或者
set
注入要使用的服务。
案例一(基本流程)
1
.
对所有的服务都要提出对外的接口
如我们要实现一个查询用户服务,需要首先进行接口声明
:
????? ??
2
.实现以上接口
3
.将该服务配置到
IOC
容器中:(独立配置文件如
UserManagerService_spring.xml
)
??????
?
4.
在整个服务的
app.config
文件中加入
UserManagerService_spring.xml
,通过
app.config
加入
UserManagerService
服务。?????????
5. 服务容器定义:
要求:单例模式
*
将
IUsersManagerService
接口交给
ServiceContainer
管理
[
对于这种模块管理以单例模式进行设计
]
?
说明: 关于“Spring/Context”的含义
:
首先,我们要添加Spring.Contet命名空间的引用,以便用IApplication接口访问IoC容器。然后解析配置文件的“Spring/Context”节点(即应用程序配置文件中一个Spring节点下的Context子节点)得到一个IApplicationContext对象,接下来的事情就是向该Context索要相关的对象
(IUsermanageService),context.GetObject("UserManageService"),其中“UserManageService”由配置文件指定生成方式和注入方式。
?
6.
使用服务容器
??
?
?
?
案例二(组合服务)
1.?????
现在我们要增加一个服务模块ICompanyManageService代码如下
:
其中在此服务中我们需要UsersMangerService服务,下面将介绍怎样将UsersMangerService服务与ICompanyManageSercice服务进行组合。
2.
上述接口的实现类
}
3.
将该服务配置到
IOC
容器中并且将案例一中的
IUserManageService
服务注入到其中:
4.通过spring框架对实例进行调用:
在此案例中我们将UserManageService服务给CompanyManageSercice提供服务支持这样就完成了服务的组合。
?
三:实现依赖注入的方式
1.
设值注入:
??
通过 setter 方法设定依赖关系显得更加直观,更加自然。 如果依赖关系(或继承关系)较为复杂, 设值注入 往往更为简洁。
2
构造子注入:
( 1 ) 避免了繁琐的 setter 方法的编写,所有依赖关系均在构造函数中设定,依赖关系集中呈现, ( 2 ) 由于没有 setter 方法,依赖关系在构造时由容器一次性设定,因此组件在被创建之后即处于 相对 “ 不变 ” 的稳定状态,无需担心上层代码在调用过程中执行 setter 方法对组件依赖关系 产生破坏,特别是对于 Singleton 模式的组件而言,这可能对整个系统产生重大的影响。 ( 3 ) 同样,由于关联关系仅在构造函数中表达,只有组件创建者需要关心组件内部的依赖关系。 对调用者而言,组件中的依赖关系处于黑盒之中。对上层屏蔽不必要的信息,也为系统的 层次清晰性提供了保证。 ( 4 ) 通过构造子注入,意味着我们可以在构造函数中决定依赖关系的注入顺序,对于一个大量 依赖外部服务的组件而言,依赖关系的获得顺序可能非常重要。
四.进行单元测试
?
项目开发的过程中,程序需要单元测试,在
spring.net
的机制中
,
可以自行完成一个测试类。
??? ????????
然在进行测试之前,必须完成对
CompanyManageService
的依赖注入
。
五.对于配置文件的定义标准:
?????
不同服务采用不同的文件进行配置,然后在一个总的配置文件中提供对这些服务配置文件的引用。这样方便对单个服务进行测试。步骤如下:
(
1
)针对服务类添加一个单独配置文件
UserManageService.xml
?
六.利用O/R mapping机制完成调用UserService服务:
?
1.???????
建立数据表
(
在
Test
数据库中
)
数据库为 SQLServer2000 ,表名为: users ?
?
2.
建立对象
实体对象名称为
Users
?
3.
建立
XML
对像映射文件
文件名称
Users.hbm.xml
(此文件应该和Users.cs文件放在同一个目录下)
注意事项:在Visual Studio 2003/2005中要将此文件的属性设置为“嵌入的资源”(Embedded Resource),SpringNHibernateSample是这个项目的名称,
此时,完成了数据表和实体类之间的映射。
?
4.
在
Spring.NET
的容器中添加
Nhibernate
的配置(
Spring_nhibernate.xml
)
????????????<entry?
key="hibernate.connection.provider"?value="NHibernate.Connection.DriverConnectionProvider"/>?
????????????<entry? key="hibernate.dialect"?value="NHibernate.Dialect.MsSql2000Dialect"/>?
????????????<entry? key="hibernate.connection.driver_class"?value="NHibernate.Driver.SqlClientDriver"/>?? ????????</dictionary> ????</property>? ?</object>? ?<object?id="HibernateTransactionManager"?type="Spring.Data.NHibernate.HibernateTransactionManager,?Spring.Data.NHibernate">? ????<property?name="DbProvider"?ref="DbProvider"/> ????<property?name="sessionFactory"?ref="SessionFactory"/> ?</object> ? ?<object?id="TransactionInterceptor"? type="Spring.Transaction.Interceptor.TransactionInterceptor,?Spring.Data"> ????<property?name="TransactionManager"?ref="HibernateTransactionManager"/> ????<property?name="TransactionAttributeSource"> ????????<object? type="Spring.Transaction.Interceptor.AttributesTransactionAttributeSource,?Spring.Data"/>? ????</property>? ?</object> ?<!--? 以下是业务相关的 ?-->
<object id="UsersManagerService"
?type="Sample.NHibernate.NHibernateTest.UsersManagerService,SpringNHibernateSample">
??????? <property name="SessionFactory" ref="SessionFactory"/>
?</object>
</objects>
需要解释的是:对于每一个大的模块我们都要建立起
Spring_nhiberate.xml
这样的文件所以为了我们的管理最好是将这种
spring.net
的配置文件放在项目根目录的一个文件夹里,然后将
spring_nhibernate.xml
这种文件交给
app.config
文件去管理
?
5.
对
Spring.NET
的容器进行初始化(
app.config
)
??app.config
文件是在项目启动的同时就进行加载的,所以当我们把
Spring_nhibernate.xml
文件放在此文件中进行管理时,在项目启动的时候
Spring_nhibernate.xml
也就被装载了
?
6.
添加一个人员管理服务(完整的过程)
?
创建一个服务接口
IUsersManagerService
:
????????????????????????
??????
?}
*
将
IUsersManagerService
接口交给
ServiceContainer
管理
[
对于这种模块管理我们需要将以单例模式进行设计
]
public
class ServiceContainer
{
?? private ServiceContainer Instance;
??
private
IUsersManagerService userService;
public
IApplicationContext context;
private
static ServiceContainer serviceContainer=null;
?? ????private ServiceContainer()
??? ??{
??? ??}
??? public static ServiceContainer Instance
{
??? get{
??????? if (serviceContainer == null)
??????? {
??????????? serviceContainer = new ServiceContainer();
??????????? context = ConfigurationSettings.GetConfig("spring/context") as IApplicationContext;
??????? }
??????? return serviceContainer;
?????? }
}
public
IUsersManagerService UserService
??? {
??????? get
{
?? ???????userService = context.GetObject("UserServiceImp") as
IUsersManagerService;
?? ???????return userService;
?
?????????? }
?? ?}
}
实现
IUsersManagerService
接口并且继承
HibernateDaoSupport
,对于
HibernateDaoSupport
类,是一个
spring.net
框架提供的类,加入
spring.net
支持后,便可以继承
HiberanteDaoSupport
这个类。
using
System;
using
System.Collections;
using
Spring.Data.NHibernate.Support;
namespace
?Sample.NHibernate.NHibernateTest
{
??? public class UsersManagerService : HibernateDaoSupport,IUsersManagerService?????
??? {
?????????? public bool SaveObject(Users user)
??????? {
??????????? HibernateTemplate.Save(user);
??????????? return true;
??????? }
??????? public bool DeleteObject(Users user)
??????? {
??????????? HibernateTemplate.Delete(user);
??? ???????return true;
??????? }
??????? public bool UpdateObject(Users user)
??????? {
??????????? HibernateTemplate.Update(user);
??????????? return true;
??????? }
??????? public IList GetAllObjectsList()
??????? {
??????????? return HibernateTemplate.LoadAll(typeof(Users));
??????? }
??????? public User Load(Object ID)
??????? {
??????????? return (User)HibernateTemplate.Load(typeof(Users),ID);
??????? }
??? }
}
7.
将UsersManagerService服务添加到具体模块中使用(UsersManager.cs)
using?System;
namespace Sample.NHibernate.NHibernateTest { ?? public class UsersManager
?? {
private
ServiceContainer.Instance.IUsersManagerService;?//
在这里通过ServiceContainer直接可以调用UserService服务,当然这个服务是在spring.net里注入过的
public
void insertUser???????
?????? {???????????????
???????????? Users newUser = null;
??????????? try
??????????? {
??????????????? newUser = usersManagerService .load("joe_cool");
??????????? }
??????????? catch
??????????? {}
??????????? if(newUser==null)
??????????? {
??????????????? newUser = new Users();
??????????????? newUser.Id = "joe_cool";
??????????????? newUser.UserName = "Joseph Cool";
??????????????? newUser.Password = "abc123";
??????????????? newUser.EmailAddress = "joe@cool.com";
?????????????? usersManagerService.SaveObject(newUser);
??????????? }
?? }
?}
至此,利用
ormapping
操作数据完成
?
(以下还在完善中)
七.如何通过Spring.Net定义Web Service以及在客户端调用Web Service
1.
消除对.asmx的依赖
}
这是一个普通的类型,其中应用了两个.NET特性:方法级的[WebMethod]及类型级的[WebService]。开发人员可以在VS.NET中创建这个服务类。
要想将这个对象发布为web服务,只需依次作以下操作:
1.
在web.config文件中,将Spring.Web.Services.WebServiceFactoryHandler注册为响应*.asmx请求的HTTP Handler。
当然,也可以为*.asmx请求注册其它的Http Handler来处理意外情况,不过一般没这个必要,因为如果
WebServiceFactoryHandler
无法在容器中找到与某个请求相匹配的对象定义,就会求助于.NET标准的Http
Handler
去查找.asmx文件。
2.
为web服务创建XML对象定义
注意
,为web服务创建的对象定义并不要求一定是抽象的(通过设置abstract="true"),但设为抽象可防止创建不必要的服务实例,因为.NET基础框架会在后台自动为每次请求创建新的服务实例,Spring.NET需要做的只是提供服务的类型名,即便标记为抽象,也能从容器中获取服务对象的实例。所以Spring.NET建议将Web服务的定义显示标记为抽象。
现在就能以对象定义中name属性的值为服务名来访问这个Web服务了:
http://localhost/MyWebApp/HelloWorld.asmx
另一种:
1.??????
新建一个webservice 项目,名为
“
WebserviceTest
”
。
2.?????????
新建一个webservice 类,名为
“
Hello
”
,并添加一个
“
HelloWorld
”
方法,代码如下:
3.??????
使用上面我们创建的
“
EnterpriseClient
”
项目,添加一个接口
“
IHello
”
,代码如下:
4.??????
填写配置文件
5.??????
在Main方法中添加下面的代码:
6.??????
运行程序,能够得到下面的结果:
?
八.
业务规则层的优势
:
业务规则层的设计的最根本的原因是
:
希望对繁杂的服务和对象进行高效且有条理的管理
,
通过
IOC
机制的灵活性
,
将系统的扩展性和低耦合性实现到较为理想的状态
,
清楚地规划出项目本身的逻辑层次
,
在业务规则层规定的实现机制下
,
提高项目的弹性
.
规则业务层中所有的服务都是要实现对应接口
,
面向接口编程是此层次的主导思想
,
也是运用
spring.net
所要实现的最终目标
,
而对于项目的扩展性主要体现在以下的几个方面
:
(1)????
如何实现新增模块
新增模块的增加首先需要声明一个属于这个模块的接口
,
此后要实现一个这个接口实体类
,
主要完成对这项功能的具体操作
.
在这里重要的是要将这个接口利用
IOC
机制注入到
IOC
容器中
,
让
spring.net
框架对其进行管理
.
由于
IOC
的注入
,
我们可以为此接口配置不同的模块解决方案
,
项目的低耦合性在于
,
当我们需要对模块进行变更我们可以完全不去对已经实现好的模块进行内部代码的修改
,
我们要做的只是在
spring.net xml
文件中将为此接口声明配置的模块更换为一个设计好的模块就可以了
,
这样不但大大简化了开发工作的工作量和产生
bug
的几率
,
同时也可以很优雅的保持了项目中的逻辑架构
,
同时我们可以扩展出属于此接口下规范下的模块
,
实现项目的良好的扩展性
.
(2)????
如何实现新增服务
对于一个模块来说
,
它需要许多的服务对其进行支持
,
那么如何将服务按照设计思想随意的加入到模块中去呢
?
我们可以将这些服务通过
IOC
机制组合到模块中
,
对于服务本身的添加我们可以按照新增模块的方式进行
IOC
注入
,
服务的增加可以任意的根据自己的需求配置到所需要的模块中
,
如若项目在以后需要为某个模块添加新的服务
,
也可以在
IOC
容器中进行扩充
,
然后再相应的实现类的构造方法中进行扩展就可以
.
同样不会影响到项目中的其他部分
,
实现了良好的低耦合度和扩展性
.
(3)????
如何变更服务
对于某些模块中的服务变更我们可以通过
IOC
机制对服务进行动态变更
,
随着项目的不同阶段
,
对项目的各种变化
,
都可以较为容易的进行服务的拼装和安插
,
在这些过程中不会影响到整个项目的架构
.
(4)????
数据库服务
数据库服务和其他的服务的实现方式相同,她它是所有服务中复用率最高的服务,它的使用机制和其他服务或许并不太一样,它的主要职责是为其他服务提供服务,是将此服务通过
IOC
注入到其他服务中去,对其他服务进行辅助,它会用到
spring.net
的实体映射机制,对数据库进行映射,同样的我们可以为了以后的某些需要来实现出这个服务的不同版本,也同样可以通过
IOC
机制对这个服务进行变更,不会影响到项目的整体结构
(编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |