Spring.Net学习 控制反转(IoC)和面向切面编程(AOP)
在开始写之前,先给出spring.net官方网站,在那里有大家所需要的例子和教程。
Spring.Net有两个很重要的感念就是IoC(控制反转)和DI(依赖注入)。
控制反转通俗的讲就是将对象的控制权转移给外部容器,即控制权的转移。
例:
有一个IUser接口和一个继承了他的类UseDAO,传统的实现我们会采取直接实例化接口
IUser user = new UserDAO
或者通过一个工厂类来创建这个接口的实例。
IUser dal = UserFactory.CreateUserDao();
但通过spring.net的IoC实现,可以这么来写
IApplicationContext ctx = new XmlApplicationContext("~/SpringConfig/spring.xml");
IUser user = (IUser)ctx.GetObject("UserDAO")
这实际上就把UserDAO的实现交给容器处理。
上面只是简单的介绍了IoC的基本感念。具体应用看下面内容。
首先来看看项目结构
NSpring.AOP:AOP通知层
NSpring.Model:实体层
NSpring.IDAL:DAO接口层
NSpring.DAL:DAO层
NSpring.Service:服务层
NSpring.BLL:业务层
NSpring:Web前端
对于项目结构,在这里不做多说,只是为了演示Spring.Net的IoC和AOP的实现。如果有什么更好的建议,欢迎大家指正。
对于具体代码这里就不贴了,等下一起打包附上。只做一些关键部分。
spring.net的配置
1 <?xml version="1.0" encoding="utf-8" ?>
2 <objects xmlns="http://www.springframework.net" >
3
4 <description>An example that demonstrates simple IoC features.</description>
5
6 <!-- UserDAO class -->
7 <object id="UserDAO" type="NSpring.DAL.UserDAO,NSpring.DAL"></object>
8
9 <!-- UserService 对象默认为singleton模式布署 -->
10 <object id="UserService" type="NSpring.Service.UserService,NSpring.Service" singleton="false">
11
12 <!-- 构造函数注入 通过索引匹配参数,也可以通过name和type来匹配-->
13 <constructor-arg index="0" value="构造函数注入的值"></constructor-arg>
14
15 <!-- 属性注入 name指属性的名称 ref指上面的object -->
16 <property name="_user" ref="UserDAO"></property>
17 <property name="MsgInfo" value="属性注入的值"></property>
18 </object>
19
20 <!-- 环绕通知 -->
21 <object id="UserAdvice" type="NSpring.AOP.UserAdvice,NSpring.AOP"></object>
22
23 <object id="exampleService" type="Spring.Aop.Framework.ProxyFactoryObject">
24 <property name="target" ref="UserService" /><!-- 拦截目标 -->
25 <property name="interceptorNames">
26 <list>
27 <value>UserAdvice</value><!-- 具体通知 -->
28 </list>
29 </property>
30 </object>
31
32 </objects>
在上面的配置文件中,<object>标签标示的是一个对象 id是这个对象的标示并且是唯一的,type指向这个对象的具体位置。
在上面的UserService中包含了属性和构造函数的注入,先来看看UserService类
1 namespace NSpring.Service
2 {
3 /// <summary>
4 /// 用户service
5 /// </summary>
6 public class UserService:IUserService
7 {
8 private IUser _user;
9 private string _msg;
10 private string _constructor;
11
12 //构造函数注入
13 public UserService(string constructor)
14 {
15 this._constructor = constructor;
16 }
17
18 //通过属性注入 相当于替代了 IUser _user = new UserDAO把这个过程交给容器来处理
19 public IUser User
20 {
21 get { return this._user; }
22 set { this._user = value; }
23 }
24
25 /// <summary>
26 /// 消息内容通过属性注入
27 /// </summary>
28 public string MsgInfo
29 {
30 get { return this._msg; }
31 set { this._msg = value; }
32 }
33
34 /// <summary>
35 /// 添加用户
36 /// </summary>
37 /// <param name="u"></param>
38 /// <returns></returns>
39 public User AddUser(User u)
40 {
41 return User.AddUser(u);
42 }
43
44 /// <summary>
45 /// 发送消息
46 /// </summary>
47 /// <returns></returns>
48 public string SendMsg()
49 {
50 return "注入的MsgInfo值是:" + MsgInfo + "<br/>" + "_constructor通过构造函数注入的值:" + _constructor;
51 }
52 }
53 }
在代码中User属性和_constructor分别通过IoC容器来进行注入。
在配置文件23行开始是AOP(面向切面编程)的配置。关于具体概念可以参考中文文档和Spring.Net官网。
<object id="UserAdvice" type="NSpring.AOP.UserAdvice,NSpring.AOP"></object>
上面这句是配置一个通知类型,在这里用的是环绕通知(还有前置、异常、后置等通知)。
本例子只是做为spring.net的测试项目。对于spring.net的IoC和AOP的初步试验,更多关于spring.net的特性还是参考官方为准,那里提供了丰富的示例项目。
自己最近在学习spring.net,但是没有在实际的项目中使用过,因此对如何更好的使用spring.net的功能也不是很了解,希望有经验的朋友可以指点下。