您的位置:首页 > 编程语言 > C语言/C++

使用Autumn框架进行C++依赖注入示例

2007-08-04 14:19 417 查看

1.1. Autumn简介

Autumn Framework是一个C++的依赖注入(DI)框架,它的功能是模仿JAVA领域中的Spring框架来的。当前只是提供依赖注入功能,而且尽量做到对原代码的不侵入。因为C++没有象JAVA那样的动态反射机制,不能很容易地在运行时得到注入的一些相关信息,所以在使用Autumn的时候,需要做一些工作来让Autumn框架知道注入时所需要的一些信息,即使用Autumn自带的一个工具AutumnGen来生成一些Wrapper文件。
通过使用Autumn,可以将动态库很容易地跟原来的程序部署在一起,而不需要重新编译原有程序。
Autumn可以从这儿下载并编译,当前最新版本是0.5.0。

1.2. Autumn示例

例子很简单。文件Action.h中定义了一个接口Action,如下:

class Action {
public:
virtual string excute(const char* s) = 0;
};

对该接口做一些不同的实现,然后在我们的程序中调用。

1.2.1. 不使用Autumn的开发过程

我们在文件LowerAction.h中对接口做一个实现LowerAction(因为比较简单,所以没有写.cpp文件),如下:

class LowerAction: public Action{
private:
string Message;

public:
LowerAction(const char* msg){
this->Message = msg;
}

string excute(const char* s){
string r = this->Message + ", " + s;
for( int i = 0; i < r.length(); i++)
r[i] = tolower(r[i]);

return r;
}
};

在文件UpperAction.h中对接口做另一个新的实现UpperAction,如下:

class UpperAction: public Action{
private:
string Message;

public:
void setMessage(const char* msg){
this->Message = msg;
}

string excute(const char* s){
string r = this->Message + ", " + s;
for( int i = 0; i < r.length(); i++)
r[i] = toupper(r[i]);

return r;
}
};

现在写主程序。
开始我们想调用LowerAction这个实现:

#include <iostream>
#include "Action.h"
#include "LowerAction.h"

int main(int argc, char* argv[])
{
Action* pa = new LowerAction(“Hello”);
cout<<pa->excute("Vincent")<<endl;
delete pa ;

return 0;
}

在主程序中,为LowerAction传入构造参数。编译主程序后,可得到运行结果:
hello, vincent

后来,我们想调用UpperAction这个实现,我们需要修改主程序,如下:

#include <iostream>
#include "Action.h"
#include "UpperAction.h"

int main(int argc, char* argv[])
{
UpperAction* pua = new UpperAction();
pua->setMessage("Hello");

Action* pa = pua;
cout<<pa->excute("Vincent")<<endl;
delete pa;

return 0;
}

在主程序中需要为UpperAction的实例设置属性Message。编译主程序后,可得到运行结果:
HELLO, VINCENT

当想换用不同的实现时,我们需要做以下几项工作:
w 修改主程序(原来是要new一个LowerAction,后来要new一个UpperAction);
w 为不同的实现进行实例化相关的一些操作,比如设置属性;
w 重新编译程序。

1.2.2. 使用Autumn的开发过程

Autumn框架尽量做到对原来代码不侵入,所以,使用Autumn框架时,接口文件Action.h及实现文件LowerAction.h和UpperAction.h都不需要修改。使用Autumn开发,大概有如下五个步骤。

1.2.2.1. 生成Wrapper文件

为那些需要Autumn来操作的类(主要是那些用来注入或被注入的类)生成Wrapper。使用AutumnGen可以根据C++的头文件自动生成相关的Wrapper文件。在本示例中为LowerAction和UpperAction生成Wrapper,命令如下:
AutumnGen LowerAction.h UpperAction.h
执行后生成四个文件:LowerAction_Wrapper.h、LowerAction_Wrapper.cpp、UpperAction_Wrapper.h、UpperAction_Wrapper.cpp。

1.2.2.2. 生成动态库

Autumn主要是基于动态库来实现灵活的依赖注入的。我们要把需要Autumn来操作的类及其Wrapper编译到一个动态库中。在本示例中,我们将实现LowerAction、UpperAction及其Wrapper都编译到一个动态库ActionImpl.dll中。

1.2.2.3. 编写配置文件

实现类都存在于ActionImpl.dll中,我们想让其提供LowerAction的实现,可以编写如下一个配置文件autumnDemo.xml:

<?xml version="1.0" encoding="UTF-8"?>
<autumn>
<library path="../lib/ActionImpl.dll" name="ActionImpl">
<beans>
<bean class="LowerAction" name="TheAction">
<constructor-arg>
<argument>
<value>Hello</value>
</argument>
</constructor-arg>
</bean>
</beans>
</library>
</autumn>

Autumn的配置文件采用XML格式,相应的schema文件autumn.xsd在源码包中。本配置文件中指出了动态库的路径(../lib/ActionImpl.dll),实现类的类名(LowerAction),实现类在Autumn中的命名(TheAction),实现类的构造参数(”Hello”)等内容。

1.2.2.4. 编写主程序

主程序中使用Autumn的BeanFactory来取得想使用的实现类,调用其excute方法。程序如下:

#include <iostream>
#include <exception>
#include "Action.h"
#include "IBeanFactory.h"

using namespace std;

int main(int argc, char* argv[])
{
try{
Autumn::IBeanFactory* bf;

bf = Autumn::getBeanFactoryWithXML("autumnDemo.xml");
Action* pa = (Action*)bf->getBean("TheAction");

cout<<pa->excute("Vincent")<<endl;

bf->freeBean(pa);
Autumn::deleteBeanFactory(bf);
}catch (const exception& e ) {
cout<<"Exception: "<<e.what()<<endl;
}
return 0;
}

主程序中首先取得BeanFactory,然后调用其getBean方法来取得实现类,用完之后,通过其freeBean来释放该实现类,程序最后释放BeanFactory。Autumn框架中的接口都在名字空间Autumn中。程序编译时需要连接Autumn框架的库文件AutumnFramework.lib(在非Windows平台上是libAutumn.so)。
按照上面1.2.2.3. 中的配置文件,使用的实现类是LowerAction,运行主程序,结果如下:
hello, vincent

1.2.2.5. 换用不同的实现

如果想不用LowerAction,而去使用UpperAction这个实现,可以修改配置文件如下:

<?xml version="1.0" encoding="UTF-8"?>
<autumn>
<library path="../lib/ActionImpl.dll" name="ActionImpl">
<beans>
<bean class="UpperAction" name="TheAction">
<properties>
<property name="Message" type="char*">
<value>Hello</value>
</property>
</properties>
</bean>
</beans>
</library>
</autumn>

保存配置文件后,不需要重新编译任何程序,直接运行主程序,结果如下:
HELLO, VINCENT
如果想更改实现类的属性值,也不需要修改程序,只需要修改Autumn的配置文件即可。修改LowerAction的属性值,只要修改配置文件中的构造参数即可,如把Hello改为Hi;同样如果想修改UpperAction的属性值,只要修改配置文件中它的名字为Message的属性的值即可。
从这儿下载示例源代码
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: