Spring ActionScript入门教程(3)-Spring和Cairngorm的结合使用[下]

本文接上一部分继续完成RSS阅读器实例,在上个部分中我们完成了Lib项目的构建,其实已经基本上完成了项目本身的逻辑代码,而在这一部分,我们将把这个Lib引入到IoC框架中,并编写相应的XML配置文件,最终完成装配,形成完整的应用。

Part4 实现主项目SpringActionScriptCairngormDemo

让我们回到SpringActionScriptCairngormDemo,开始完成IoC的注入工作。

4.1 配置编译参数

 打开项目属性,在编译参数部分,将项目依赖的SWC文件都设置好,包括两部分:一部分是已经下载到libs目录下的SWC文件,还要把我们上个例子中编译好的SpringActionScriptCairngormDemoLib.swc也配置进去,配置参数应该如下:

-locale en_US -default-background-color #000000  -include-libraries   ../libs/spring-actionscript.swc ../libs/spring-actionscript-cairngorm.swc ../libs/as3commons-reflect.swc ../libs/as3commons-lang.swc ../libs/as3commons-logging.swc ../libs/flexunit.swc ../../SpringActionScriptCairngormDemoLib/bin/SpringActionScriptCairngormDemoLib.swc

参见附图:

点击查看大图

4.2 写配置XML

在src目录下,创建一个文件夹名为“config”,然后在config下面再创建两个目录,分别是cairngorm和view,第一个目录是为了存放和Cairngorm相关的配置,第二个目录是用于存放跟视图相关的配置。当然这样拆分目录是为了便于区分和维护,实际上你也可以根据需要按照自己的需要拆分目录结构,IoC对此没有硬性要求。

首先我们先来配置Cairngorm的部分,将Cairngorm部分必须的Service,ModelLocator,FrontControler等部分一一做配置。在cairngorm目录下,创建一个XML文件,名为“cairngorm.xml”。输入下面的内容:

  1. <objects>
  2.  
  3. <!--ModelLocator-->
  4. <object id="appModelInstance" class="com.riameeting.model.ApplicationModel" factory-method="getInstance" singleton="true">
  5. <property name="feedURL" value="http://www.riameeting.com/rss.xml" />
  6. </object>
  7.  
  8. <!--Service Locator-->
  9. <object id="serviceLocator" class="org.springextensions.actionscript.cairngorm.business.CairngormServiceLocator" factory-method="getInstance">
  10. <property name="feedService">
  11. <ref>feedService</ref>
  12. </property>
  13. </object>
  14. <object id="feedService" class="mx.rpc.http.HTTPService">
  15. <property name="url" value="http://www.riameeting.com/rss.xml"/>
  16. <property name="method" value="GET"/>
  17. <property name="useProxy" value="false"/>
  18. <property name="resultFormat" value="text"/>
  19. </object>
  20.  
  21. <!--Delegate Factory-->
  22. <object id="businessDelegateFactory" class="org.springextensions.actionscript.cairngorm.business.BusinessDelegateFactory">
  23. <property name="service" ref="feedService"/>
  24. <property name="delegateClass" type="class" value="com.riameeting.business.GetFeedDelegate"></property>
  25. </object>
  26.  
  27. <!--FrontControler-->
  28. <object id="appAwareCmdFactory" class="com.riameeting.factories.ApplicationModelAwareCommandFactory">
  29. <property name="applicationModel" ref="appModelInstance"/>
  30. <method-invocation name="addBusinessDelegateFactory">
  31. <arg>
  32. <ref>businessDelegateFactory</ref>
  33. </arg>
  34. <arg>
  35. <array>
  36. <value type="Class">com.riameeting.command.GetFeedCommand</value>
  37. </array>
  38. </arg>
  39. </method-invocation>
  40. </object>
  41. <object id="frontController" class="org.springextensions.actionscript.cairngorm.control.CairngormFrontController">
  42. <constructor-arg>
  43. <object>
  44. <property name="getFeedEvent" value="GetFeedCommand"/>
  45. </object>
  46. </constructor-arg>
  47. <constructor-arg value="com.riameeting.command"/>
  48. <method-invocation name="addCommandFactory">
  49. <arg><ref>appAwareCmdFactory</ref></arg>
  50. </method-invocation>
  51. </object>
  52.  
  53. </objects>

可以看到主体配置分为4个部分:

  1. ModelLocator - 对应在Lib中创建的ApplicationModel,在此创建一个Model的实例
  2. Service Locator - 先创建一个ID为“feedService”的HTTPService,然后创建一个ID为“serviceLocator”的Service Locator,将feedService引入进去
  3. Delegate Factory - 我们通过配置代理工厂,将第二部分的服务注入到代理中去,这样代理就具备了通过自身调用服务的能力,而不需要同外部服务产生直接的依赖
  4. FrontControler - 首先我们配置工厂类ApplicationModelAwareCommandFactory,将Model注入到Command中去。然后创建一个前端控制器“frontController”,将事件与命令之间建立映射。

然后我们来创建一个关于视图的配置文件,定义界面上都显示什么样的组件,在view下面创建一个XML文件,名为“global.xml”,然后输入下面的内容:

  1. <objects>
  2.  
  3. <object id="searchForm" class="com.riameeting.view.AddressBar">
  4. <property name="model" ref="appModelInstance"/>
  5. <property name="x" value="10"/>
  6. <property name="y" value="10"/>
  7. </object>
  8. <!--<object id="searchResult" class="com.riameeting.view.SearchResultWithTable">-->
  9. <object id="searchResult" class="com.riameeting.view.SearchResult">
  10. <property name="model" ref="appModelInstance"/>
  11. <property name="x" value="10"/>
  12. <property name="y" value="60"/>
  13. </object>
  14. <object class="com.riameeting.utils.ApplicationViewAssembler" init-method="init">
  15. <property name="elements">
  16. <value>
  17. <array>
  18. <ref>searchForm</ref>
  19. <ref>searchResult</ref>
  20. </array>
  21. </value>
  22. </property>
  23. </object>
  24.  
  25. </objects>

你可以看到视图方面配置了三个部分,第一个对应我们在Lib中定义的搜索组件,ID是searchForm,第二个是用于显示Feed内容的列表组件,ID是searchResult,而第三个配置只是为了使用工具类将前两个组件添加到显示列表中。并且为每一个视图组件,都指定了Model的引用,就是我们在Cairngom.xml中配置好的Model。

然后我们定义一个主体的XML,在config下面创建一个名为“”的XML文件,引入上面创建的两个XML,内容如下:

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <objects>
  3. <import file="view/global.xml"/>
  4. <import file="cairngorm/cairngorm.xml"/>
  5. </objects>

4.3 实现IoC容器载入

打开SpringActionScriptCairngormDemo.mxml,建立一个代码块,声明一下IoC容器,载入配置文件,代码如下:

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" creationComplete="init()" layout="absolute" width="420" height="480" viewSourceURL="srcview/index.html">
  3. <mx:Script>
  4. <![CDATA[
  5. import org.springextensions.actionscript.context.support.FlexXMLApplicationContext;
  6. private function init():void {
  7. var appContextPath:String = "config/application_context.xml";
  8. var context:FlexXMLApplicationContext = new FlexXMLApplicationContext(appContextPath);
  9. context.addEventListener(Event.COMPLETE,onIoCLoadComplete);
  10. context.load();
  11. }
  12. private function onIoCLoadComplete(e:Event):void {
  13. trace("loaded");
  14. }
  15. ]]>
  16. </mx:Script>
  17. </mx:Application>

编译并运行项目,就可以看到运行结果了。

演示地址:

http://www.riameeting.com/examples/SpringASCairngormDemo/SpringActionScriptCairngormDemo.html

提示:你可以在Demo上点击右键查看源码。

附件中是两个项目的源码下载。

Lib项目

Demo项目

riadevID: 
您给予的分值: None 平均分: 10 ( 4 票)

为什么要独立创建lib项目呢?

首先,谢谢楼主的教程,很详细,很容易入门。其次我在运行这个demo的时候,也出现了点小问题:
1.新建的lib工程时,mxml文件在flex标准工程中不可以inport.dubug会出现找不到类的错误。但是楼主的是可以的,原因我锁定在lib项目上,可是没找到具体是为什么!
2.为何要分成两个项目呢?这是spring机制必须 还是楼主刻意为之。
3.我尝试合二为一时,发现找不到类错误。
4.楼主讲解了程序的流程,但是没有讲解为何这么运行,即程序从哪里启动,简单讲 就是程序代码运行的流程。我初学,所以很多不懂。
5.我又在想 caringorm框架 内部耦合较高,spring是用来解耦,所以我想修改修改这些代码,是否能够以更少的xml配置量达到解耦的要求。
如果楼主或是路人阅过此留言,期待建议。
有这方面的爱好者 欢迎切磋 email: wushexin2006@126.com

自己对自己的回复,不足之处,见谅

呵呵 这是我自己对自己的回复。其实上叙所有的问题 要是可以合二为一那就什么都解决了。今天看了一天的英文文档,终于找到了一个解。可能不是最好的解,但也确实暂时解决了这个问题。

我的思路也就是将合二为一。在楼主的代码中 将demolib项目中src下的源代码 拷贝到 demo的src下,将demo的编译时参数改为

-locale en_US -default-background-color #000000 -include-libraries ../libs/spring-actionscript.swc ../libs/as3commons-reflect.swc ../libs/as3commons-lang.swc ../libs/as3commons-logging.swc ../libs/flexunit.swc

如果此时dubug,还是会发现找不到xxx类。原因是swc文件找不到类,因为没有在任何时候告诉他xxx类已经编译进来了。原本楼主的解决方案也是很好的。但是我这里的解决方案是 新增一个配置文件。ClassReferences.properties 放到src目录下就好了。文件的中内容如下:

GetFeedCommand = ClassReference("com.riameeting.command.GetFeedCommand")
ApplicationModel = ClassReference("com.riameeting.model.ApplicationModel")
AddressBar = ClassReference("com.riameeting.view.AddressBar")
SearchResult = ClassReference("com.riameeting.view.SearchResult")
ApplicationViewAssembler = ClassReference("com.riameeting.utils.ApplicationViewAssembler")
ApplicationModelAwareCommandFactory = ClassReference("com.riameeting.factories.ApplicationModelAwareCommandFactory")
GetFeedDelegate = ClassReference("com.riameeting.business.GetFeedDelegate")

其次要在主应用程序mxml中加入一个变量定义。下面修改后的 SpringActionScriptCairngormDemo.mxml


creationComplete="init()" layout="absolute"
width="420" height="480" viewSourceURL="srcview/index.html">

import mx.resources.ResourceBundle;

import org.springextensions.actionscript.context.support.FlexXMLApplicationContext;

[ResourceBundle("ClassReferences")]
private var springClassRefs:ResourceBundle;

private function init():void {
var appContextPath:String = "config/application_context.xml";
var context:FlexXMLApplicationContext = new FlexXMLApplicationContext(appContextPath);
context.addEventListener(Event.COMPLETE,onIoCLoadComplete);
context.load();
}
private function onIoCLoadComplete(e:Event):void {
trace("loaded");
}
]]>

至此 运行程序 将和楼主的一样。这是提供了一种解决方案,如果哪位大师有更好的解法,我们洗耳恭听。还有楼主说,希望大家多社区交流,将riameeting发扬光大。

分成两个项目是为了

分成两个项目是为了方便把所有的类编译到主工程中,这个倒不是Spring的强制要求,只要你能保证主项目在使用IoC的时候,能包含所需要的类即可。因为在Flex中使用IoC很容易出现这样的问题:我写了一个类,只会在IoC装配的时候会使用到,而没有在实际的代码中引用到,这样Flex编译的时候会把这个类排除在外,会导致运行时找不到所需的类。

关于流程,简单来讲,要分成两个方面来看:IoC部分,应用在加载配置的XML完毕之后,就由IoC容器开始装配所有配置的Bean,Cairngorm部分,我们是用事件来驱动,所有的执行动作会映射为一个命令的实例来运行

工厂的配置

呵呵 程序运行的流程我已经明白了 谢谢楼主热心释疑!现在还有一点问题是配置中的 工厂配置我有点不好理解。配置工厂有何用?而又是如何配置的呢?
及下面代码的中的第一个object配置



businessDelegateFactory



com.riameeting.command.GetFeedCommand












appAwareCmdFactory

代码应该是这段




businessDelegateFactory



com.riameeting.command.GetFeedCommand












appAwareCmdFactory

关于FLEX Liberary project的使用

你好,这个sample工程把很多具体实现的代码都放在liberary project里面生成SWC文件,个人认为这样做有待商榷,如果业务变更或者增加一些功能岂不是要重新生成SWC文件,从而影响rsl的效率.使用Lib工程是不是应该把共同不经常变更的东西打包作为Lib使用呢?

您好,您的想法是正

您好,您的想法是正确的,这个例子足够简单,所以我没有拆分,实际上您可以根据需要拆分出不同的SWC,比如公用的类是一个SWC,而其它部分再作为其它的SWC存在,或者使用RSL,只要满足IOC的前提(依赖的类必须可以找到)就可以。

我直接引用了网上编译的lib也不行啊!

我的开发环境 myeclipse 6.5+flex3.2 插件版!
我flexbuid3.0 直接引用网上代码呢!只能出现空白窗口,真晕

我编译过是可以的,

我编译过是可以的,或许你该进Debug模式仔细看看,SpringActionScript的SWC似乎有些问题,有警告信息输出,不知大家遇到过没有

Debug无法跟踪

有qq吗能联过来帮忙看看吗?我qq:914440226

发表新评论

  • 网页地址和电子邮件地址将会被自动转换为链接。
  • 行和段被自动切分。
  • 您可以使用下面的标签来高亮显示您的评论内容: <code>, <blockcode>. 可以使用"[foo]".旁边显示标签样式 "<foo>" PHP代码可以用这样的区块来包含<?php ... ?> or <% ... %>

更多格式化选项信息

验证区域
系统验证:请回答下面的问题