一.具体介绍
目的:降低业务逻辑层耦合和进行动态加载提高系统的可扩展性
使用工具:
spring.net
框架
通过
IOC
注入机制实现
二.具体机制
新增模块规范描述如下
:
当系统需要添加新服务—
>
首先声明该服务接口—
>
实现该服务接口—
>
将此实例注入到
spring.net IOC
容器—
>
将此服务放入
ServiceContainer
统一进行管理—
>
通过模块容器(服务容器)来对服务进行调用,也可以通过构造或者
set
注入要使用的服务。
案例一(基本流程)
public interface IUserManageService
{
///<summary>
///</summary>
///<returns></returns>
string GetUserInfo();
}
|
2
.实现以上接口
class
UserManageSerciceImpl : IUserManageService
{
public
UserManageSerciceImpl()
{
}
public
string GetUserInfo()
{
User
user = new User();
user.Oid = 1;
user.Name = "Beniao";
user.Sex = "Boy";
user.Age = 25;
return
string.Format("
编号:{0}--->姓名:{1}--->性别:{2}--->年龄:{3}"
,
user.Oid,
user.Name,
user.Sex,
user.Age);
}
}
|
<
object
name
=
"UserManageService"type="TestSprintNet.ServiceImpl.UserManageSerciceImpl,TestSprintNet" />
|
4.
在整个服务的
app.config
文件中加入
UserManagerService_spring.xml
,通过
app.config
加入
UserManagerService
服务。?????????
5. 服务容器定义:
要求:单例模式
*
将
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();
}
return serviceContainer;
}
public IUsersManagerService UserService
{
get {
|
|
userService = context.Getobject("UserServiceImp") as IUsersManagerService;
//
通过IOC注入在这里得到UserService实例对象
return userService;
}
}
}
|
|
说明: 关于“Spring/Context”的含义
:
首先,我们要添加Spring.Contet命名空间的引用,以便用IApplication接口访问IoC容器。然后解析配置文件的“Spring/Context”节点(即应用程序配置文件中一个Spring节点下的Context子节点)得到一个IApplicationContext对象,接下来的事情就是向该Context索要相关的对象
6.
使用服务容器
public
class UsersManager
{
private UsersmangerService usersManagerService=ServiceContainer.Instance.IUsersManagerService;(
在这里通过ServiceContainer直接可以调用IUsersManagerService服务,当然这个服务是在spring.net里注???????、??入过的) //具体使用
……………………
..
}
|
案例二(组合服务)
namespace
TestSprintNet.ServiceInterface
{
public interface ICompanyManageSercice
{
string getAllUser();
}
}
|
2.
上述接口的实现类
class
CompanyManageServiceImpl : ICompanyManageSercice
{
private IUserManageService _userManage;
private IUserManageService _userManageService;
//
构造器注入(注入
IUserManageService
服务
)
public CompanyManageServiceImpl(IUserManageService userManageService)
{
|
|
this._userManageService = userManageService;
}
public string getAllUser()
{
//return _userManage.GetUserInfo();
return _userManageService.GetUserInfo();
}
}
|
}
3.
将该服务配置到
IOC
容器中并且将案例一中的
IUserManageService
服务注入到其中:
<
object
name
=
"CompanyManageService"type="TestSprintNet.ServiceImpl.CompanyManageServiceImpl,TestSprintNet">
//set
注入组合方式:
<
property
name
="
userManageService
"
ref
="
UserManageService
"
/>???????
//
构造子注入组合方式:
<
constructor-arg
name
=
"userManageService"ref="UserManageService"/>
</
object
>
|
4.通过spring框架对实例进行调用:
ICompanyManageSercice
companyManageService = context.Getobject("CompanyManageService") as ICompanyManageSercice;
Console
.WriteLine(companyManageService.getAllUser());
|
在此案例中我们将UserManageService服务给CompanyManageSercice提供服务支持这样就完成了服务的组合。
三:实现依赖注入的方式
<
object
name
=
"CompanyManageService"type="TestSprintNet.ServiceImpl.CompanyManageServiceImpl,TestSprintNet">
<
property
name
=
"UserManage"ref="UserManageService"/>
</
object
>
|
2
构造子注入:
( 1 ) 避免了繁琐的 setter 方法的编写,所有依赖关系均在构造函数中设定,依赖关系集中呈现,
( 2 ) 由于没有 setter 方法,依赖关系在构造时由容器一次性设定,因此组件在被创建之后即处于
相对 “ 不变 ” 的稳定状态,无需担心上层代码在调用过程中执行 setter 方法对组件依赖关系
产生破坏,特别是对于 Singleton 模式的组件而言,这可能对整个系统产生重大的影响。
( 3 ) 同样,由于关联关系仅在构造函数中表达,只有组件创建者需要关心组件内部的依赖关系。
对调用者而言,组件中的依赖关系处于黑盒之中。对上层屏蔽不必要的信息,也为系统的
层次清晰性提供了保证。
( 4 ) 通过构造子注入,意味着我们可以在构造函数中决定依赖关系的注入顺序,对于一个大量
依赖外部服务的组件而言,依赖关系的获得顺序可能非常重要。
( 1 ) 避免了繁琐的 setter 方法的编写,所有依赖关系均在构造函数中设定,依赖关系集中呈现,
( 2 ) 由于没有 setter 方法,依赖关系在构造时由容器一次性设定,因此组件在被创建之后即处于
相对 “ 不变 ” 的稳定状态,无需担心上层代码在调用过程中执行 setter 方法对组件依赖关系
产生破坏,特别是对于 Singleton 模式的组件而言,这可能对整个系统产生重大的影响。
( 3 ) 同样,由于关联关系仅在构造函数中表达,只有组件创建者需要关心组件内部的依赖关系。
对调用者而言,组件中的依赖关系处于黑盒之中。对上层屏蔽不必要的信息,也为系统的
层次清晰性提供了保证。
( 4 ) 通过构造子注入,意味着我们可以在构造函数中决定依赖关系的注入顺序,对于一个大量
依赖外部服务的组件而言,依赖关系的获得顺序可能非常重要。
<
object
name
=
"CompanyManageService"
type
=
"TestSprintNet.ServiceImpl.CompanyManageServiceImpl,TestSprintNet">
<
constructor-arg
name
=
"UserManageService"ref="UserManageService"/>
</
object
>
|
四.进行单元测试
namespace
TestSprintNet
{
static class Program
{
static void Main()
{
try
{
IApplicationContext context = ConfigurationSettings.GetConfig("spring/context") as IApplicationContext; ICompanyManageSercice companyManageService = context.Getobject("CompanyManageService") as ICompanyManageSercice; Console.WriteLine(companyManageService.getAllUser());
Console
.Read();
} catch(Exception e)
{
}
}
}
}
|
然在进行测试之前,必须完成对
CompanyManageService
的依赖注入
。
五.对于配置文件的定义标准:
<?
xml
version
=
"1.0"encoding="utf-8" ?>
<
objects
>
<!--
您的对象定义
-->
<
object
name
=
"UserManageService"type="TestSprintNet.ServiceImpl.UserManageSerciceImpl,TestSprintNet" />
</
objects
>
<
spring
>
<
context
>
|
</
context
>
<
objects
xmlns
=
"http://www.springframework.net"/>
</
spring
>
|
六.利用O/R mapping机制完成调用UserService服务:
字段名称
|
类型
|
长度
|
varchar
|
50
|
|
UserName
|
varchar
|
50
|
Password
|
varchar
|
50
|
EmailAddress
|
varchar
|
50
|
2.
建立对象
实体对象名称为
Users
namespace
Sample.NHibernate.NHibernateTest
{ public class Users { private string id; private string userName; private string password; private string emailAddress; public User() { } public string Id { get { return id; } set { id = value; } } public string UserName { get { return userName; } set { userName = value; } } public string Password { get { return password; } set { password = value; }
public
string
EmailAddress
{ get { return emailAddress; } set { emailAddress = value; } } }
}
|
3.
建立
XML
对像映射文件
<
?xml version
=
"
1.0
" encoding
=
"utf
-
8
" ?
>
< hibernate - mapping xmlns = "urn:nhibernate - mapping - 2.0 " > < class name = " Sample.NHibernate.NHibernateTest.User, SpringNHibernateSample " table = "users" > < id name = "Id" column = "logonId" type = "String" length = " 50 " > < generator class = "assigned" /> </ id > < property name = "UserName" column = "UserName" type = "String" length = " 40 " /> < property name = "Password" column = "Password" type = "String" length = " 20 " /> < property name = "EmailAddress" column = "EmailAddress" type = "String" length = " 40 " /> </ class > </ hibernate - mapping > |
<?xml version="1.0" encoding="utf-8" ?>
<objects xmlns='http://www.springframework.net'> <object id="DbProvider" type="Spring.Data.Common.DbProviderFactoryObject,Spring.Data"> <property name="Provider" value="sqlServer-2.0"/> <property name="ConnectionString" value="server=(local);user id=sa;pwd=;database=Test"/> </object>
<object id="SessionFactory"
type="Spring.Data.NHibernate.LocalSessionFactoryObject, Spring.Data.NHibernate">
<property name="DbProvider" ref="DbProvider"/> <property name="MappingAssemblies"> <list> <value>SpringNhibernateSample</value> </list> </property> <property name="HibernateProperties"> <dictionary> |
<entry
key="hibernate.connection.provider" value="NHibernate.Connection.DriverConnectionProvider"/>
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>
<!-- 以下是业务相关的 -->
<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
也就被装载了
|
using
System;
using
System.Collections;
|
|
using
Spring.Data.NHibernate.Support;
namespace
Sample.NHibernate.NHibernateTest.Interface;
interface
IUsersManagerService
{
public bool SaveObject(Users user);
public bool DeleteObject(Users user);
public bool UpdateObject(Users user);
public IList GetAllObjectsList();
public User Load(Object ID);
|
|
}
*
将
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();
}
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)
{
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 = "[email protected]";
usersManagerService.SaveObject(newUser);
}
}
}
至此,利用
ormapping
操作数据完成
(以下还在完善中)
七.如何通过Spring.Net定义Web Service以及在客户端调用Web Service
1.
消除对.asmx的依赖
namespace
MyComany.MyApp.Services
{
[WebService(Namespace = "http://myCompany/services")]
public class HelloWorldService
{
[WebMethod]
public string HelloWorld()
{
return "Hello World!";
}
}
|
}
要想将这个对象发布为web服务,只需依次作以下操作:
<
httpHandlers
>
<
add
verb
=
"*"path="*.asmx"type="Spring.Web.Services.WebServiceHandlerFactory,
Spring.Web
"/>
</
httpHandlers
>
|
当然,也可以为*.asmx请求注册其它的Http Handler来处理意外情况,不过一般没这个必要,因为如果
WebServiceFactoryHandler
无法在容器中找到与某个请求相匹配的对象定义,就会求助于.NET标准的Http
Handler
去查找.asmx文件。
2.
为web服务创建XML对象定义
<
object
name
=
"HelloWorld.asmx"type="MyComany.MyApp.Services.HelloWorldService,MyAssembly"abstract="true"/>
|
注意
,为web服务创建的对象定义并不要求一定是抽象的(通过设置abstract="true"),但设为抽象可防止创建不必要的服务实例,因为.NET基础框架会在后台自动为每次请求创建新的服务实例,Spring.NET需要做的只是提供服务的类型名,即便标记为抽象,也能从容器中获取服务对象的实例。所以Spring.NET建议将Web服务的定义显示标记为抽象。
现在就能以对象定义中name属性的值为服务名来访问这个Web服务了:
另一种:
[WebService(Namespace="http://www.websharp.org/webservices/")]
public class Hello : System.Web.Services.WebService
{
[WebMethod]
public string HelloWorld()
{
return "Hello World";
}
}
|
public
interface IHello
{
string HelloWorld();
}
|
4.
填写配置文件
url
="http://localhost/webservicetest/hello.asmx"
namespace
="http://www.websharp.org/webservices/"
/>
|
public
static void Main(string[] args)
{
IHello hello1= ServiceLocator.FindService
("HelloWorldWebService",typeof(IHello)) as IHello;
Console.WriteLine(hello1.HelloWorld());
Console.ReadLine();
}
|
6.
运行程序,能够得到下面的结果:
八.
业务规则层的优势
:
业务规则层的设计的最根本的原因是
:
希望对繁杂的服务和对象进行高效且有条理的管理
,
通过
IOC
机制的灵活性
,
将系统的扩展性和低耦合性实现到较为理想的状态
,
清楚地规划出项目本身的逻辑层次
,
在业务规则层规定的实现机制下
,
提高项目的弹性
.
(1)
如何实现新增模块
新增模块的增加首先需要声明一个属于这个模块的接口
,
此后要实现一个这个接口实体类
,
主要完成对这项功能的具体操作
.
在这里重要的是要将这个接口利用
IOC
机制注入到
IOC
容器中
,
让
spring.net
框架对其进行管理
.
由于
IOC
的注入
,
我们可以为此接口配置不同的模块解决方案
,
项目的低耦合性在于
,
当我们需要对模块进行变更我们可以完全不去对已经实现好的模块进行内部代码的修改
,
我们要做的只是在
spring.net xml
文件中将为此接口声明配置的模块更换为一个设计好的模块就可以了
,
这样不但大大简化了开发工作的工作量和产生
bug
的几率
,
同时也可以很优雅的保持了项目中的逻辑架构
,
同时我们可以扩展出属于此接口下规范下的模块
,
实现项目的良好的扩展性
.
(2)
如何实现新增服务
对于一个模块来说
,
它需要许多的服务对其进行支持
,
那么如何将服务按照设计思想随意的加入到模块中去呢
?
我们可以将这些服务通过
IOC
机制组合到模块中
,
对于服务本身的添加我们可以按照新增模块的方式进行
IOC
注入
,
服务的增加可以任意的根据自己的需求配置到所需要的模块中
,
如若项目在以后需要为某个模块添加新的服务
,
也可以在
IOC
容器中进行扩充
,
然后再相应的实现类的构造方法中进行扩展就可以
.
同样不会影响到项目中的其他部分
,
实现了良好的低耦合度和扩展性
.
(3)
如何变更服务
对于某些模块中的服务变更我们可以通过
IOC
机制对服务进行动态变更
,
随着项目的不同阶段
,
对项目的各种变化
,
都可以较为容易的进行服务的拼装和安插
,
在这些过程中不会影响到整个项目的架构
.
(4)
数据库服务
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。