admin 管理员组

文章数量: 1184232


2024年1月13日发(作者:解释程序是)

教程

目 录

教程(一)控制反转(依赖注入)(基础篇) ............................................................................................................................................................................ 3

教程(二)环境搭建(基础篇) ............................................................................................................................................................................................... 7

教程(三)实现一个简易的IoC框架(练习篇) ................................................................................................................................................................. 10

教程(四)对象的创建(基础篇) ......................................................................................................................................................................................... 13

教程(五)容器中对象的作用域(基础篇) ......................................................................................................................................................................... 16

教程(六)依赖注入(应用篇) ............................................................................................................................................................................................. 21

教程(七)依赖对象的注入(基础篇) 上 ........................................................................................................................................................................... 26

教程(八)集合类型的注入(基础篇) ................................................................................................................................................................................. 29

教程(九)打造简易的依赖注入框架(练习篇) ................................................................................................................................................................. 34

教程(十)方法的注入(基础篇) ......................................................................................................................................................................................... 40

教程(十一)自定义对象行为(基础篇) ............................................................................................................................................................................. 45

教程(十二)面向切面编程(基础篇) ................................................................................................................................................................................. 47

教程(十三)AOP的概念(基础篇) .................................................................................................................................................................................... 53

教程(十四)AOP的通知类型(基础篇) ............................................................................................................................................................................ 56

教程(十五)AOP的配置(基础篇) .................................................................................................................................................................................... 62

教程(十六)事务管理(应用篇) ......................................................................................................................................................................................... 72

教程(十七)事务传播行为(基础篇) ................................................................................................................................................................................. 83

教程(十八)整合NHibernate(基础篇) ............................................................................................................................................................................. 86

教程(十九)整合NHibernate和 MVC(基础篇) ........................................................................................................................................... 101

教程(二十)整合Remoting(应用篇) .............................................................................................................................................................................. 116

教程(二十一)整合Web Service(应用篇) ..................................................................................................................................................................... 121

教程(二十二)整合(应用篇) ...................................................................................................................................................................... 126

教程(二十三)整合NVelocity(应用篇) ......................................................................................................................................................................... 130

教程(一)控制反转(依赖注入)(基础篇)

在学习这个控制反转(IoC)和面向切面(AOP)的容器框架之前,我们先来看一下什么是控制反转(IoC)。

控制反转(Inversion of Control,英文缩写为IoC),也叫依赖注入(Dependency Injection)。我个人认为控制反转的意思是依赖对象(控制权)发生转变,由最初的类本身来管理依赖对象转变为IoC框架来管理这些对象,使得依赖脱离类本身的控制,从而实现松耦合。

我们先来看一段代码

namespace Dao

{

public interface IPersonDao

{

void Save();

}

public class PersonDao : IPersonDao

{

public void Save()

{

ine("保存 Person");

}

}

}

namespace SpringNetIoC

{

class Program

{

private static void NormalMethod()

{

IPersonDao dao = new PersonDao();

();

ine("我是一般方法");

}

}

}

Program必然需要知道IPersonDao接口和PersonDao类。为了不暴露具体实现,我可以运用设计模式中的抽象工厂模式(Abstract Factory)来解决。

namespace DaoFactory

{

public static class DataAccess

{

public static IPersonDao CreatePersonDao()

{

return new PersonDao();

}

}

}

namespace SpringNetIoC

{

class Program

{

private static void FactoryMethod()

{

IPersonDao dao = PersonDao();

();

ine("我是工厂方法");

}

}

}

这时,Program只需要知道IPersonDao接口和工厂,而不需要知道PersonDao类。然后我们试图想象,要是有这样的工厂框架帮我们管理依赖的对象就好了,于是控制反转出来了。

一个简单的控制反转例子

Program

using System;

using c;

using ;

using ;

using Dao;

using DaoFactory;

using t;

/>

using t;

namespace SpringNetIoC

{

class Program

{

static void Main(string[] args)

{

//NormalMethod();// 一般方法

//FactoryMethod();// 工厂方法

IoCMethod();// IoC方法"

ne();

}

private static void NormalMethod()

{

IPersonDao dao = new PersonDao();

();

ine("我是一般方法");

}

private static void FactoryMethod()

{

IPersonDao dao = PersonDao();

();

ine("我是工厂方法");

}

private static void IoCMethod()

{

IApplicationContext ctx = text();

IPersonDao dao = ect("PersonDao") as IPersonDao;

if (dao != null)

{

();

ine("我是IoC方法");

}

}

}

}

一个简单的控制反转程序例子就实现了。

这样从一定程度上解决了Program与PersonDao耦合的问题,但是实际上并没有完全解决耦合,只是把耦合放到了XML 文件中,通过一个容器在需要的时候把这个依赖关系形成,即把需要的接口实现注入到需要它的类中。我个人认为可以把IoC模式看做是工厂模式的升华,可以把 IoC看作是一个大工厂,只不过这个大工厂里要生成的对象都是在XML文件中给出定义的。

教程(二)环境搭建(基础篇)

一、环境下载及安装

到Spring的官方网站下载框架的安装文件()。目前最新的版本是1.3。下载并解压后就可以了。

我们使用框架经常用到的一下几个文件:

(必要)

(必要)

(可选)

在以后的博客里我们会学习一些与NHibernate和 MVC结合的例子,可以到Hibernate的官方网站和的官方网站下载各自的框架安装文件。

在基于XML的工厂中,这些对象定义表现为一个或多个子节点,它们的父节点必须是(按:objects节点的xmlns元素是必需的,必须根据不同的应用添加不同的命名空间,以便有IDE的智能提示(见中文手册)。

xmlns:xsi="/2001/XMLSchema-instance"

xsi:schemaLocation="

/xsd/">

同样也可以找到解压目录下的-1.3.0-RC1docschema,把里面的几个.xsd复制到VS2008安装目录下的Microsoft Visual Studio 9.0XmlSchemas文件夹。

必要的时候可以安装建立程序的模板

二、建立一个应用程序

我们新建一个的文件,然后从手册中复制来一段配置模板

xmlns:xsi="/2001/XMLSchema-instance"

xsi:schemaLocation="

/xsd/">

目前我找到了实例化容量的两种方式:

1.实际物理路径

IResource input = new FileSystemResource(@"D:");//实际物理路径

IObjectFactory factory = new XmlObjectFactory(input);

2.程序集下寻找配置文件

string[] xmlFiles = new string[]

{

"file://"

};

IApplicationContext context = new XmlApplicationContext(xmlFiles);

IObjectFactory factory = (IObjectFactory)context;

ne();

目前我一般采用后者(程序集下寻找配置文件),这样维护起来比较方便。

这种方式需满足URI语法。

file://文件名

assembly://程序集名/命名空名/文件名

然而更好的方式是在配置文件或添加自定义配置节点

在配置文件中要引入命名空间,否则程序将会无法实例化容器。

IApplicationContext ctx = text();ine(ect("PersonDao").ToString());

好了,的环境配置就先讲到这里。

教程(三)实现一个简易的IoC框架(练习篇)

讲了这么多理论,我们来手动实现一个简易的IoC框架的,这样可以加深IoC的理论知识。

一、思路

在我们使用框架的时候,首先需要实例化容器, 然后调用IoC容器IObjectFactory接口中GetObject方法获取容器中的对象。通过这一点就可以告诉我们制作IoC容器需要写一个获取 XML文件内容的方法和申明一个Dictionary来存放IoC容器中的对象,还需要写一个能从Dictionary中获取对象的方法。

二、分析

要获取XML文件的内容,在3.5的语法中,我自然而然想到了Linq To XML。需要实例XML中配置的对象,我们想到了使用反射技术来获取对象的实例。

三、代码实现

工厂

MyXmlFactory

using System;

using c;

using ;

using ;

using ;

using tion;

namespace MyselfIoC

{

public class MyXmlFactory

{

private IDictionary objectDefine = new Dictionary();

public MyXmlFactory(string fileName)

{

InstanceObjects(fileName);// 实例IoC容器

}

///

/// 实例IoC容器

///

///

private void InstanceObjects(string fileName)

{

XElement root = (fileName);

var objects = from obj in ts("object")objectDefine = ionary(

k => ute("id").Value,

v =>

{

string typeName = ute("type").Value;

Type type = e(typeName);

return Instance(type);

}

);

}

///

/// 获取对象

///

///

///

public object GetObject(string id)

{

object result = null;

if (nsKey(id))

{

result = objectDefine[id];

}

return result;

select obj;

}

}

}

2.调用

Program

using System;

using c;

using ;

using ;

namespace MyselfIoC

{

class Program

{

static void Main(string[] args)

{

AppReGIStry();

ne();

}

static void AppRegistry()

{

MyXmlFactory ctx = new MyXmlFactory(@"D:");

ine(ect("PersonDao").ToString());

}

}

}

好了,一个简易的IoC框架就基本实现了。

教程(四)对象的创建(基础篇)

学过了前面的课程,我们来一起学习的IoC容器对象的创建。

创建对象一般有3种方式:1.构造器创建,2.静态工厂创建,3.实例工厂创建

多数情况下,容器会根据对象定义中的type属性值去直接调用相应类型的某个构造器。另外,容器也可以调用工厂方法来创建对象,这时type属性的值就应该是包含工厂方法的类型(按:而不是要创建的类型,但通过该对象定义的名称获取的则是由工厂方法所创建的对象)。工厂方法的产品对象可以是工厂方法所在的类型,也可以是其它类型(按:很多情况下工厂方法位于单独的类型中),这无关紧要。(摘自中文手册)

一、通过构造器创建对象

通过构造器创建对象需要满足这几个条件:1.指明对象类型type="类全名,程序集名"(

type="Dao, CreateObjects" />),也可以使用强命名type=", ,

Version=2.0.0.0, Culture=neutral,PublicKeyToken=b77a5c561934e089"。2.有一个无参的构造函数或者默认构造函数。

CreateByConstructor

///

/// 构造器创建

///

static void CreateByConstructor()

{

string[] XMLFiles = new string[]

{

"assembly://CreateObjects/CreateObjects/"

};

IApplicationContext context = new XmlApplicationContext(xmlFiles);

IObjectFactory factory = (IObjectFactory)context;

ine(ect("personDao").ToString());

}

嵌套类型对象的创建需要用“+”号来连接被嵌套的类型。如果在PersonDao中嵌套了类型Person

CreateNested

/**////

/// 嵌套类型创建

///

static void CreateNested()

{

string[] XMLFiles = new string[]

{

"assembly://CreateObjects/CreateObjects/"

};

IApplicationContext context = new XmlApplicationContext(xmlFiles);

IObjectFactory factory = (IObjectFactory)context;

ine(ect("person").ToString());

}

二、静态工厂创建

使用静态工厂创建对象需要配置factory-method属性

/**////

/// 静态工厂创建

///

static void CreateByStaticFactory()

{

string[] xmlFiles = new string[]

{

"assembly://CreateObjects/CreateObjects/"

};

CreateObjects"factory-method="CreateInstance"/>

IApplicationContext context = new XmlApplicationContext(xmlFiles);

IObjectFactory factory = (IObjectFactory)context;

ine(ect("staticObjectsFactory").ToString());

}

三、使用实例工厂创建对象

使用实例工厂创建对象需要先定义一个工厂,然后设置factory-object和factory-method属性,且满足 实例工厂方法所在的对象必须也要配置在同一容器(或父容器)中 和 对象定义就不能包含type属性

instanceObjectsFactory

CreateByInstanceFactory

/**////

/// 实例工厂创建

///

static void CreateByInstanceFactory()

{

string[] XMLFiles = new string[]

{

"assembly://CreateObjects/CreateObjects/"

};

IApplicationContext context = new XmlApplicationContext(xmlFiles);

IObjectFactory factory = (IObjectFactory)context;

ine(ect("instancePersonDao").ToString());

}

四、泛型类型的创建

泛型类型的创建比较类型于以上几种创建方式,可以有通过构造器创建,还可以通过静态或者实例工厂创建。但是设置type属性的时候要注意:左尖括号<要替换成字符串“<”,因为在XML中左尖括号会被认为是小于号。

CreateGenericClass

/**////

/// 创建泛型

///

static void CreateGenericClass()

{

string[] xmlFiles = new string[]

{

"assembly://CreateObjects/CreateObjects/"

};

IApplicationContext context = new XmlApplicationContext(xmlFiles);

IObjectFactory factory = (IObjectFactory)context;

object obj = ect("genericClass");

ine(ng());

}

以上就是对象创建的几种方式。

教程(五)容器中对象的作用域(基础篇)

容器中对象的部署分为两种方式:singleton和非singleton(Java里叫prototype)。这里的singleton指的是“单例模式”,就是说当一个对象被定义为singleton时,容器中就只会有一个共享的实例,任何时候通过id或别名请求该对象都会返回这个共享实例的引用(也就是说这个对象只会被创建一次)。当使用非singleton,或者说原型模式布署时,每次请求对象都会创建新的实例。在某些场合,如果需要为每个用户返回单独的用户对象或其它对象,非singlton布署模式就比较理想。默认为singleton模式。每次调用GetObject方法时得到的都是同样的实例;当singleton="false"时,每次调用GetObject方法时得到的则是不同的实例。

CreateWithSingleton

[Test]

public void CreateWithSingleton()

{

string[] XMLFiles = new string[]

{

"assembly://SpringNetScop/SpringNetScop/"

};

IApplicationContext context = new XmlApplicationContext(xmlFiles);

IObjectFactory factory = (IObjectFactory)context;

object obj1 = ect("personDao");

object obj2 = ect("personDao");

al(obj1, obj2);

}

我们用NUnit可以看到下图:

使用singleton="false"的代码

CreateWithOutSingleton

[Test]

public void CreateWithOutSingleton()

{

string[] XMLFiles = new string[]

{

"assembly://SpringNetScop/SpringNetScop/"

};

IApplicationContext context = new XmlApplicationContext(xmlFiles);

IObjectFactory factory = (IObjectFactory)context;

object obj1 = ect("person");

object obj2 = ect("person");

Equal(obj1, obj2);

}

Person

public class Person

{

public Person()

{

ine("Person被实例");

}

public override string ToString()

{

return "我是Person";

}

~Person()

{

ine("Person被销毁");

图为:

这说明singleton=false后,每次调用GetObject方法获取的对象是不同实例的,当脱离调用方法(CreateWithOutSingleton)的作用域后,该实例会被容器销毁。

lazy-init属性是指:当容器初始化的时候标注该属性的对象将被实例化,反之则是调用GetObject方法的时候才被实例化。

CreateWithLazy

[Test]

public void CreateWithLazy()

{

string[] XMLFiles = new string[]

{

"assembly://SpringNetScop/SpringNetScop/"

};

IApplicationContext context = new XmlApplicationContext(xmlFiles);

IObjectFactory factory = (IObjectFactory)context;

object dao = ect("personDao");

ine(ng());

object server = ect("personServer");

ine(ng());

}

PersonServer

public class PersonServer

{

public PersonServer()

{

ine("PersonServer被实例");

}

public override string ToString()

{

return "我是PersonServer";

}

}

如图:

PersonDao类未设置lazy-init属性,则当初始化时被实例;PersonServer类设置lazy-init="true",则当调用GetObject方法时才被实例。

一般情况下可以有选择的设置lazy-init属性,正如双刃剑一样,设置为lazy-init=true的时候应用程序启动时会快一点,但是在启动的时候就不能够帮我们检测错误,但当调用的时候一旦发生错误,后果是不堪设想的。

更多资料请查看中文手册。

教程(六)依赖注入(应用篇)

谈到高级语言编程,我们就会联想到设计模式;谈到设计模式,我们就会说道怎么样解耦合。而的IoC容器其中的一种用途就是解耦合,其最经典的应用就是:依赖注入(Dependeny Injection)简称DI,目前DI是最优秀的解耦方式之一。下面我就来谈谈依赖注入的应用场景。

我模拟了三种不同的场景,可以一起学习使用依赖注入的重要性。

下面是应用场景的条件:人类使用工具劳动。

/**////

/// 抽象人类

///

public abstract class Person

{

/**////

/// 使用工具劳动

///

public abstract void Work();

}

public interface ITool

{

/**////

/// 使用工具

///

void UseTool();

}

场景一,原始社会:原始人使用长矛打猎

public class Spear : ITool

{

public void UseTool()

{

ine("使用长矛");

}

}

PrimitivePerson

public class PrimitivePerson : Person

{

/**////

/// 原始社会使用长矛打猎

///

public override void Work()

{

//知道打猎使用的是长矛,并且制造长矛

ITool tool = new Spear();

l();

ine("使用长矛打猎");

}

}

从上面代码我们不难看出,虽然使用的经典的里氏替换原则,但PrimitivePerson类于Spear类存在着耦合。

场景二,经济社会:使用工具耕作

public class Hoe : ITool

{

public void UseTool()

{

ine("使用锄头");

}

}

ToolFactory

public static class ToolFactory

{

/**////

/// 工厂制造工具

///

///

public static ITool CreateTool()

{

return new Hoe();// 制造锄头

}

}

EconomyPerson

public class EconomyPerson : Person

{

/**////

/// 经济社会使用锄头耕作

///

public override void Work()

{

//不用知道什么工具,只需知道工厂能买到工具,而不自己制造工具,但仅由工厂制造锄头

ITool tool = Tool();

l();

ine("经济社会使用工具耕作");

}

}

从上面代码我可以看出:运用的经典的工厂模式, EconomyPerson仅仅对工厂耦合,并不关心工厂是怎样制造工具。

场景三,现在社会:使用工具办公

public class Computer : ITool

{

public void UseTool()

{

ine("使用电脑");

}

}

ModernPerson

public class ModernPerson : Person

{

/**////

/// 从外部获取工具

///

public ITool Tool { get; set; }

/**////

/// 现在人用不需要知道电脑是哪来的,直接拿来办公

///

public override void Work()

{

//不知道使用什么工具和哪来的工具,只是机械化的办公

l();

ine("使用工具办公");

}

}

一个简单的控制反转例子

Program

class Program

{

static void Main(string[] args)

{

IApplicationContext ctx = text();

Person person = (Person)ect("modernPerson");

();

ne();

}

}

从上面代码我们可以看出,把对象交给容器进行管理,ModernPerson类不需要知道具体使用什么工具,仅仅是机械化的工作。至于使用的什么工具,则由配置文件决定,所有对象由容器管理,这样可以实现动态的拆装组建和组件重用。我个人理解依赖注入是反射工厂的加强版。

教程(七)依赖对象的注入(基础篇) 上

一、属性注入

上篇我们简单提到依赖注入的用途。回顾一下所讲内容,发现在object节点下使用了。而property 标签正是用来属性注入的。而ref是用来标识是关联到哪个object。而name属性是指属性名。如下:

值类型的注入是需要使用property 节点的value属性。如

作为内联类型可以使用如下:

同理,内联类型可以是循环引用的对象(见代码处)。

二、构造函数注入

构造器注入使用constructor-arg标签作为标识。同样具有于属性注入相同的方式,使用name、ref、value作为构造器注入的属性,如下:

程序的代码如下:

public class Person

{

public string Name { get; set; }

public int Age { get; set; }

public Person Friend { get; set; }

}

PersonDao

public class PersonDao

{

private Person argPerson;

private int intProp;

public PersonDao(Person argPerson, int intProp)

{

son = argPerson;

p = intProp;

}

public void Get()

{

//构造函数注入的整型参数

ine(("intProp:{0}", intProp));

//构造函数注入的Person

ine(("argPerson Name:{0}", ));

ine(("argPerson Age:{0}", ));

//内联对象Friend

ine(("argPerson Friend Name:{0}", ));

ine(("argPerson Friend Age:{0}", ));

//内联对象的循环引用

ine(("argPerson Friend Friend Name:{0}", ));

ine(("argPerson Friend Friend Age:{0}", ));

}

}

/>

Program

class Program

{

static void Main(string[] args)

{

IApplicationContext ctx = text();

PersonDao dao = ect("personDao") as PersonDao;

();

ne();

}

}

输出效果如下:

教程(八)集合类型的注入(基础篇)

还支持集合类型的注入。而且使用起来也比较方便。

一、ILIst类型

使用元素作为ILIst的标签,value为集合中元素的值。也可以注入对象,甚至关联其它对象,使用 元素表示关联的对象,object 属性为所关联对象的id或name。集合可以为空,用元素来标记。

元素中设置 element-type 属性表示泛型T的类型,例如 element-type="int" ,代表int型。

二、IDictionary类型

使用元素来表示IDictionary接口的实现类型。表示IDictionary集合的元素。key和value属性为元素的键值队,value-ref为关联的元素。

同理,元素的key-type和value-type属性来表示泛型value-type="object"> 。

完整代码如下:

Domain

public class Happy

{

public override string ToString()

{

return "每天都开心,每天都有好心情";

}

}

public class OneYear

{

public override string ToString()

{

return "快乐的一年";

}

}

public class Person

{

public IList BestFriends { get; set; }

public IList HappyYears { get; set; }

public IList Years { get; set; }

IDictionary,例如

public IDictionary HappyDic { get; set; }

public IDictionary HappyTimes { get; set; }

}

1992

1998 年

/>

1992

1998

2000

Program

class Program

{

static void Main(string[] args)

{

IApplicationContext ctx = text();

Person person = ect("person") as Person;

ine("空值");

string bestFriend = iends == null ? "我的朋友太多了"ine(bestFriend);

ine();

ine("IList");

foreach (var item in ears)

{

ine(item);

}

ine();

ine("泛型Ilist");

foreach (int item in )

{

ine(item);

}

ine();

ine("IDictionary");

foreach (DictionaryEntry item in ic)

{

ine( + " 是 " + );

}

ine();

ine("泛型IDictionary");

foreach (KeyValuePair item in imes)

{

: "我只有一个好朋友";

ine( + " 是 " + );

}

ne();

}

}

输入结果如下:

教程(九)打造简易的依赖注入框架(练习篇)

我们在第三篇中学习里一个简易的IoC框架。今天我们接着上次的程序,实现带参数构造函数对象的实例和属性的注入。

我们知道可以通过反射获取类的构造函数及参数(GetConstructors方法);可以获取属性和属性的类型(GetProperties方法)。通过Activator的CreateInstance(Type type, params object[] args)方法可以创建带参数构造函数的实例。通过SetValue方法可以给属性赋值,这

样一来,我们就上次的代码稍加改造就可以实现属性的注入了。

下面是完成的代码:

Domain

public class Person

{

public string Name { get; set; }

public int Age { get; set; }

}

public class PersonDao

{

private int intProp;

public PersonDao(int intProp)

{

p = intProp;

}

public Person Entity { get; set; }

public override string ToString()

{

return "构造函数参数intProp为:" + p;

}

}

ObjectFactory

public class ObjectFactory

{

private IDictionary objectDefine =

private ObjectFactory(string fileName)

{

InstanceObjects(fileName);// 实例IoC容器

DiObjects(fileName);// 属性注入

}

new Dictionary();

private static ObjectFactory instance;

private static object lockHelper = new object();

public static ObjectFactory Instance(string fileName)

{

if (instance == null)

{

lock (lockHelper)

{

instance = instance ?? new ObjectFactory(fileName);

}

}

return instance;

}

/**////

/// 实例IoC容器

///

///

private void InstanceObjects(string fileName)

{

XElement root = (fileName);

var objects = from obj in ts("object")

select obj;

//无参构造函数

objectDefine = (obj =>

t("constructor-arg") == null).ToDictionary(

k => ute("id").Value,

v =>

{

string typeName = ute("type").Value;

Type type = e(typeName);

return Instance(type);

}

);

//有参构造函数

foreach (XElement item in (obj =>

t("constructor-arg") != null))

{

string id = ute("id").Value;

string typeName = ute("type").Value;

Type type = e(typeName);

var args = from property in structors()[0].GetParameters()

join el in ts("constructor-arg")

on equals ute("name").Value

select Type(ute("value").Value,

terType);

object obj = Instance(type, y());

(id, obj);

}

}

/**////

/// 属性注入

///

///

private void DiObjects(string fileName)

{

XElement root = (fileName);

var objects = from obj in ts("object")

select obj;

foreach (KeyValuePair item in objectDefine)

{

foreach (var el in (e =>

ute("id").Value == ).Elements("property"))

{

Type type = e();

//获取属性

foreach (PropertyInfo property in perties())

{

if ( == ute("name").Value)

{

if (ute("value") != null)

{

//设置属性值

ue(,

Type(ute("value").Value,

tyType), null);

}

else if (ute("ref") != null)

{

object refObject = null;

if (nsKey(ute("ref").Value))

{

refObject = objectDefine[ute("ref").Value];

}

//设置关联对象属性

ue(, refObject, null);

}

}

}

}

}

}

/**////

/// 获取对象

///

///

///

public object GetObject(string id)

{

object result = null;

if (nsKey(id))

{

result = objectDefine[id];

}

return result;

}

}

Program

class Program

{

static void Main(string[] args)

{

ObjectFactory factory

ce(@"F:ExerciseSpringNetStep1SpringNet_");

PersonDao dao = (PersonDao)ect("personDao");

ine("姓名:" + );

ine("年龄:" + );

ine(dao);

ne();

}

}

输入结果:

=

教程(十)方法的注入(基础篇)

多数用户都会将容器中的大部分对象布署为singleton模式。当一个singleton对象需要和另一个singleton对象协作,或者一个非singleton对象需要和另一个非singleson对象协作时,都能很好的处理它们的依赖关系。但是,如果对象的生存周期不同,就可能会产生问题。例如,假设一个singleton对象A要使用一个非singleton(原型)对象B,A中的每个方法都会用到B的新实例。由于 A是singleton对象,容器只有会创建它一次,也就是说只有一次给A的属性赋值的机会,所以不可能在每次A需要的时候都给它注入一个新的B。

有一种解决的办法有点违背控制反转原则:类A可以通过实现IObjectFactoryAware接口来获取容器的引用,并调用GetObject("B")在每次需要的时候从容器中请求一个(新的)对象B。但这并不是一个很好的解决方案,因为客户代码此时必须要和发生紧耦合。

通过方法注入,我们可以用更优雅的方式解决类似的问题。(摘自中文手册)

一、查询方法注入

可以动态覆盖对象的抽象方法或虚方法,并且可以在容器内查找已命名对象,查询方法注入就利用了这些功能。个人感觉查询方法注入类似抽象工厂,为之不同的是,可以不用写抽象的实现代码,通过配置文件动态的切换组件。

在lookup-method节点配置name和object属性

实现代码如下:

LookupMethod

//注意,可以直接在配置中定义这个类的对象

public abstract class ObjectFactory

{

//或者可以是一个虚方法

public abstract PersonDao CreatePersonDao();

}

public class PersonDao

{

public void Save()

{

ine("保存数据");

}

}

二、替换任意方法

替换任意方法在项目中使用的很少,实现方法也比较复杂。至于为什么使用替换任意方法,我还不是很清楚,如果有知

道使用场景的朋友可以给我留言。我个人认为其用途是:实现非派生类方法的重写或在IoC框架中简易的AOP拦截(这一点又不确定,以后我会写AOP方面的博客)。

首先继承IMethodReplacer接口并实现Implement方法,object[] arguments为传入的参数。其次在replaced-method节点配置name和replacer属性,和增加arg-type节点且配置返回类型match属性

代码如下:

ReplacedMethod

public class UserDao

{

//虚方法

public virtual string GetValue(string input)

{

return null;

}

}

//实现IMethodReplacer接口

public class ReplaceValue : IMethodReplacer

{

public object Implement(object target, MethodInfo method, object[] arguments)

{

string value = (string)arguments[0];

return "获取到:" + value;

}

}

三、事件注入

在的IoC框架中,除了提供方法注入以外,还提供事件的注入。通过事件的注入,可以使架构体系的耦合降到最低。(参考 clingingboy的 学习笔记(3)-注册事件注入)

在listener节点处配置event和method属性指明事件名和绑定的方法,并增加ref节点设置object属性来指明调用哪个IoC容器对象。

实现代码:

Listener

//先定义一个委托

public delegate string OpenHandler(string arg);

public class Door

{

public event OpenHandler OpenTheDoor;

public void OnOpen(string arg)

{

//调用事件

if (OpenTheDoor != null)

{

ine(OpenTheDoor(arg));

}

}

}

public class Men

{

public string OpenThisDoor(string arg)

{

return "参数是:" + arg;

}

}

调用部分代码:

Program

class Program

{

static void Main(string[] args)

{

IApplicationContext ctx = text();

ine("查询方法");

ObjectFactory factory = (ObjectFactory)ect("objectFactory");

PersonDao().Save();

ine();

ine("替换方法");

UserDao dao = (UserDao)ect("userDao");

ine(ue("Liu Dong"));

ine();

ine("事件注册");

Door door = (Door)ect("door");

("Opening!");

ine();

ne();

}

}

输入效果:

教程(十一)自定义对象行为(基础篇)

通过几个专门的接口来控制容器中对象的行为。说到对象的行为无非就要提到对象的生命周期控制。类似在WinForm开发,Form生命周期中,Load方法为Form的载入方法和Dispose方法为Form的销毁方法。都能完美的实现这些需求。

一、生命周期接口

在使用框架的时候通常遇到怎样初始化和销毁非托管资源(如数据库连接)的麻烦,下面的解决方案可能对您有所帮助。

1.初始化行为

继承alizingObject接口或者配置object节点的init-method属性,的IoC框架就会帮我们在该对象被实例后调用配置好的初始化方法。

2.销毁行为

继承sable接口或者在object节点配置destroy-method属性,会帮我们在容器被销毁时调用它。

实现代码:

Person

public class Person

{

public void Init()

{

ine("我长大了");

}

public void Destroy()

{

ine("我衰老了");

}

}

init-method="Init" destroy-method="Destroy" />

二、抽象对象定义和子对象定义

对象定义可能会包含大量的信息,比如与容器相关的信息(即初始化方法、静态工厂方法名等)、构造器参数和属性值等。子对象定义是指从一个父对象定义中继承了配置数据的对象定义。子对象定义可以根据需要重写或添加某些配置的值。使用父对象和子对象的定义方式可能会节省大量的键入工作。实际上这是设计模式中模板模式的一种形式。个人认为可以解决“子类”与“父类”之间的耦合。

在object节点中设置parent属性来指明是继承关系,而并非正真意义的继承。

实现代码:

public abstract class Parent

{

public string Name { get; set; }

}

public class Child

{

public string Name { get; set; }

}

我们可以看出Child类并没有继承Parent类。

输出效果:

教程(十二)面向切面编程(基础篇)

AOP即面向切面编程(ASPect Oriented Programming的缩写),是OOP(面向对象编程)的一种延续形式。是通过预编译方式和运行期动态代理实现在不修改源代码的情况下给程序动态统一添加功能的一种技术,它从一个不同于OOP的角度来看待程序的结构:OOP将应用程序分解为一系列表现为继承关系的对象;AOP 则把程序分解为一系列方面(aspects)或者关注点(concerns)。AOP将诸如事务管理等本来横向分布在多个对象中的关注点进行了模块化处理(这些关注点也常称为横切(crosscutting)关注点)。在中提供了面向切面编程的丰富支持,允许通过分离应用的业务逻辑与系统级服务(例如审计(auditing)和事务(transaction)管理)进行内聚性的开发。应用对象只实现它们应该做的完成业务逻辑仅此而已。它们并不负责(甚至是意识)其它的系统级关注点,例如日志或事务支持。

下面我举个例子来说明这一切:

场景:业务类CompanyManager在调用Save方法的时候需要调用SecurityManager类判断权限是否足够(图1)。

图1

准备条件:

public class CompanyDao

{

public void Save()

{

ine("保存数据");

}

}

public interface ICompanyManager

{

string UserName { get; set; }

void Save();

}

public interface ISecurityManager

{

bool IsPass(string userName);

}

SecurityManager

public class SecurityManager : ISecurityManager

{

/**////

/// 判断权限

///

///

///

public bool IsPass(string userName)

{

return userName == "admin";

}

}

第一种实现方式,我们通常会这样做:直接在CompanyManager类中调用ISecurityManager接口的IsPass方法判断权限。

SimpleCompanyManager

public class SimpleCompanyManager : ICompanyManager

{

可通过外部注入的属性#region 可通过外部注入的属性

public string UserName { get; set; }

public CompanyDao Dao { get; set; }

#endregion

public void Save()


本文标签: 对象 注入 方法

更多相关文章

告别冗余:轻松掌握Word文档删除空白页的五大实用小技巧

1月前

平时使用Word写文档时,经常遇到在编辑处理完文档后会发现Word中多出了一个或多个空白页,而这些空白页上已经没有任何内容却怎么都删不了,很是苦恼。 本文主要讲解了5种经过小编测试有效的删除Word文档中空白页的方法。其中

注册表密技:一键锁定IE浏览器的起始页位置

1月前

也许有人遇到过,打开IE浏览器发现不是自己设置的主页,于是就去改主页设置,可以无论怎么修改都不行,让人头疼发蒙。这是因为一些恶意软件或木马在注册表中修改了主页的设置,导致无法使用常规的设置修改主页。今天和大家分享下如何使用注册表来锁定

xinput1_3.dll出错让你头疼?简单步骤帮你快速解决

1月前

找不到xinput1_3.dll要怎么处理?首先我们就要先了解xinput1_3.dll这个文件,只有知道这个文件了,那么才可以修复xinput1_3.dll文件,今天我们就来给大家详细的讲解一下这方面吧。 一.xinput1

卡在错误代码126上?这篇指南集合了7个实用技巧,帮你快速解决xinput1_3.dll加载失败难题!

1月前

xinput1_3.dll是Windows操作系统中一个非常关键的动态链接库(Dynamic Link Library, DLL)文件,它是微软DirectX软件开发包的组成部分,专门用于支持游戏控制器和其它输入设备在游戏及多媒体应用

电脑小白也能解决的XINPUT1_3.DLL丢失烦恼?实用技巧分享,立即重启游戏体验。

1月前

xinput1_3.dll是一个动态链接库(DLL)文件,它在Windows操作系统中扮演着重要的角色。该文件作为系统库文件,通常存放于C:WindowsSystem32目录下(对于32位系统)或C:WindowsSysWOW

优化Flash中心体验:在火狐中使用ZeroClipboard避免HTMLBridge出错

1月前

Zero Clipboard的实现原理Zero Clipboard 利用透明的Flash让其漂浮在复制按钮之上,这样其实点击的不是按钮而是 Flash ,这样将需要的内容传入Flash,再通过Flash的复制功能把传入的

面对Word文档的抗拒,如何智慧地获得它打开的秘密?

1月前

word文档打不开的常见原因?好的处理方法 最近使用办公软件经常出现打开Word文档没有响应的情况。Word是我们生活办公中常用的软件,会遇到这样的问题是不可避免的。那么遇到 word文档打不开的常见原

安卓应用开发者指南:弹幕视频功能详解

1月前

简单概述 现在有个很流行视频的效果就是 弹幕效果,满屏幕的文字从右到左飘来飘去。看的眼花缭乱,看起来还蛮cool的现在就是来实现这一的一个效果,大部分的都是从右向左移动漂移,本文的效果中也支持从左向右的

Qt快速上手:QListWidget右键菜单的个性化定制

1月前

0 前言 关于QListWidget右菜单的的实现,网上多数资料都没有提到如何使用Qt Creator快速实现[1][2],本文重点介绍此方法。本文要达到的效果是,为QListWidget控件添加2个右键菜单“Delete”和

Flash文件读取失败?一文教你轻松搞定内存问题!

1月前

内存不能为read正确修复方法2010年06月03日内存不能为read正确修复方法:内存指令不能read,这是在电脑使用中常常出现地情况,内存是主板上地存储部件,是CPU直接与之沟通,并用其寄存当前正在使用地(即

Linux中的隐蔽空间:隐藏文件全解析

1月前

在Linux中,隐藏文件以点(.)开头的文件或文件夹被认为是隐藏文件。隐藏文件通常用于存储系统配置文件或敏感文件。 以下是几种不同的方法来隐藏文件或文件夹: 方法1:在文件或文件夹名字前面加上点(.) mv fil

解锁隐藏文件夹的秘籍:轻松步骤教你显示系统中的隐藏文件

1月前

一、问题背景 有时候急着找一份重要文件,明明记得存在电脑里, 翻遍所有文件夹却连影子都看不到!是不是瞬间慌了神, 怀疑文件被误删,甚至担心电脑中病毒了? 其实不用瞎着急!

d3dcompiler43.dll丢失?别慌,这里教你3步快速找到并解决方法!

1月前

d3dcompiler_43.dll是什么文件?当你知道d3dcompiler_43.dll这个文件名字的时候,相信你是遇到了d3dcompiler_43.dll丢失的问题了!所以才会这样问,其实这就是一个普通的dll文件,对于电脑系

面对D3DCompiler_43.dll丢失,这里有个高效修复方案

28天前

dcompiler_43.dll 是一个Windows系统中的系统文件,属于DirectX软件的一部分。这个dcompiler_43.dll(动态链接库)文件主要用于处理与3D图形编程有关的任务,是运行许多游戏和高级图形程序必需的组件

不再受困:Mac上的卸载技巧,专治SWF、Flash中心等应用程序的困扰!

19天前

Mac电脑如果有太多无用的应用程序,很有可能会拖垮Mac系统的运行速度。因此,卸载电脑中无用的软件是优化Mac系统运行速度的最佳方式之一。Mac删除应用程序特别简单,长点击应用点击x,或是直接将应用拖进废纸篓。但是有一些应用长按没有x

内存优化攻略:轻松释放电脑性能,提升工作效率

19天前

电脑内存(RAM)的清理对于维持系统的流畅运行至关重要。随着使用时间的增加,系统内存会被各种应用程序和后台进程占用,导致系统响应变慢,甚至出现卡顿现象。通过有效地清理内存,可以提升电脑的性能,延长其使用寿命。本文将详细介绍如何清理电脑

内存清理大法:让你的电脑运行如飞,告别卡顿烦恼

19天前

电脑内存(RAM)的清理对于维持系统的流畅运行至关重要。随着使用时间的增加,系统内存会被各种应用程序和后台进程占用,导致系统响应变慢,甚至出现卡顿现象。通过有效地清理内存,可以提升电脑的性能,延长其使用寿命。本文将详细介绍如何清理电脑

Android7.0 数据业务长连接拨号过程_数据拨号

18天前

前面我们已经分析了android在进行数据业务拨号前,进行相关准备工作的流程,现在我们可以分析一下整个数据业务长连接拨号在框架部分的流程。 长连接的“长”,是相对于终端进行彩信发送等操作时,建立的临时数据连接而言的(这种临时数

Linux命令-CPU 使用率达到 100%_linux 让cpu占用率达100%

17天前

在 Linux 中,可以使用一些命令或方法来 临时让 CPU 使用率达到 100%(用于测试或压力测试),然后再停止这些进程,使 CPU 恢复正常。以下是几种常见的方法:方法 1:使用

java 读取模板EXCEL写入数值_excel模板通过编辑标注,java写数据

17天前

自己写了个读取excel模板的写入数据的列子 package copy.user;import java.io.File;import java.io.FileOutputStream;import java.io.IOExc

发表评论

全部评论 0
暂无评论