这篇文章很好的表达了逻辑与界面分离的思想。在eclipse的插件开发中,很常见!
文章内容:
SWT(Standard Widget Toolkit) 是 eclipse 项目的开源 GUI 编程框架,通过 JNI 来访问操作系统原生窗口部件,提供了高性能和优雅的用户界面展示。但是,使用 SWT 需要了解大量相关控件,布局,属性等的 API; 同时,构建基于 SWT 的用户界面应用也需要编写大量的 UI 逻辑代码。这不仅对编程人员的技能有一定要求,同时也会带来大量的用户界面编码工作。
那么,SWT 的用户界面一定需要使用 Java 代码作为描述方式吗?答案是否定的。
本文描述了如何使用控制反转 (IoC) 的设计思想,运用 XML 语言来描述 SWT 的用户界面,通过详实的示例,令读者不仅仅能了解到 IoC 设计思想的巧妙,更能学习到 IoC 与 SWT 共同工作的和谐之美,掌握通过解析 XML 达到创建 SWT 界面的方法,从而实现降低界面逻辑复杂性和技能门槛的目的。与此同时,作者还将通过多年的 SWT 编程经验和对桌面前端应用需求的挖掘,介绍 XML 描述 SWT 界面的优势,应用场景,以及在 IBM 产品中的体现。
|
|
随着 eclipse 插件开发和富客户端应用的日渐流行,SWT 作为 eclipse 项目的开源 GUI 编程框架,正在被广泛的使用。采用 SWT 实现的应用程序,通过 JNI 来访问操作系统原生窗口部件,提供了高性能和优雅的用户界面展示,具有的感观效果以及响应方式同本地程序几乎一模一样。对于 Java 阵营而言,这无疑是一个巨大的突破。但是,在当前 SWT 界面技术的使用过程中,在 SWT 广泛推广的道路上,仍然存在着一些需要解决的问题:
大量的开发人员,因项目的需求、客户的需要以及自身的偏好,希望投入到 SWT 用户界面的阵营,充分利用 SWT 界面的各种优势。诚然,SWT 作为一款开源的 GUI 编程框架,提供了友好的 API,在线的文档以及大量翔实的示例。但是,根据开发人员的技术水平和项目经验,学习使用 SWT 仍然需要一个技术熟悉的学习周期,少则一周,多则数月。开发人员希望得到的是 SWT 带来的各种特性,但是未必肯付出学习的成本;同时,因为项目和需求的不同,未必允许开发人员有足够的时间进行技术的熟悉。
SWT 编写的用户界面的逻辑代码,是规则的 Java 代码的堆砌,是一项代码量相当大的工作,一个较为简单的用户登录界面,很多时候也需要数百行的代码进行界面的处理。这其中包含了控件的创建,控件之间的父 子和嵌套关系,属性的设定,外观的定制,布局的管理以及校验、事件处理、数据绑定等大量业务逻辑。
界面相关的代码,不仅仅包含了界面元素的描述,很多时候还包含校验、事件处理、数据绑定等大量业务逻辑。为了保证每个界面代码的相对独立性和重用 性,多数开发人员会将校验、事件处理、数据绑定等逻辑与界面展示逻辑写在同一个类中,例如,使用大量的内部类或匿名类。这加重了界面描述与业务逻辑的耦合 度。
由于 Java 是编译型语言,所以每次对 Java 代码的修改都会需要重新编译和构建,SWT 的代码也不例外。当用户需求更改时,即使仅仅修改一个控件的颜色或者字体,都需要修改相应的 Java 代码,然后重新编译和构建,当该应用已被部署为富客户端应用时,还需要重新导出 eclipse 插件等操作,这无疑加重了维护和更新的复杂度。
基于 Java 代码解析和生成的 SWT 编辑工具是困难的,当前免费的工具更少。究其原因,与 SWT 代码的复杂性密切相关,解析复杂的界面代码是困难的工作,需要覆盖各种用户使用场景。特别是当用户图形化拖拽生成了需要的代码,然后人为的对生成的代码做 了各种修改,再逆向回到编辑器时,如何能够识别用户添加或修改的代码,是比较难做到的,同时,逆向解释 Java 代码也会带来性能和时间的消耗,带来了负面的用户体验。
|
|
控制反转的理念至今已有数年。控制反转的核心思想在于提供一种简单的机制来创建组件以及规定组件之间的依赖关系。控制反转,可以用 XML 文档作为定义文件的依托,描述 Bean 的创建方式,规定各个 Bean 之间的依赖关系,注入初始化 Bean 需要的各种属性以及逻辑。这与我们在 SWT 界面逻辑中描述的行为是一致的。 SWT 界面逻辑主要包含以下内容:SWT 控件的创建; SWT 控件之间的包含关系; SWT 控件的属性设定,例如字体,颜色,坐标等; SWT 的事件处理,校验等业务逻辑。
由此看来,使用控制反转来创建 SWT 界面逻辑,不失为一种描述 SWT 界面的方式。使用控制反转,可以做到:
- 使用 XML 文件来描述 SWT 界面逻辑,而不是使用 Java 代码。
- 将控件名称定义于 XML 文件中即可实现相应控件的初始化。
- 利用 XML 文件中标签的父子关系,规范 SWT 中控件的父子关系。
- 将事件处理,校验等业务逻辑外化,并利用控制反转的定义模式,在 XML 文件中描述,并注入到 SWT 控件中。
遵循上述特性,使用了控制反转来创建 SWT 界面逻辑,就能够一定程度上解决前面描述的各种问题,同时带给开发人员和最终用户更多的便利:
XML 是一种结构化的标准的描述语言,在各种技术和平台中被广泛的使用,开发人员普遍拥有深刻的理解和应用的经验。使用 XML 语言描述 SWT 界面,通俗易懂,省去了开发人员学习 SWT 新技术的时间,降低了客户的培训费用和实施风险。
使用简洁明了的 XML 片段替代大段的 Java 代码逻辑,节省了开发时间,缩短了实施周期。
使用控制反转注入业务逻辑,可以分离界面描述和业务描述。界面描述存在于 XML 文件之中,而业务逻辑描述存在于 Java 代码之中。在二者分离的同时,也提高了二者的可重用度。
当界面描述有必要更改时,不必修改 Java 代码,只需要更新相应的 XML 文件即可。如此,省却了编译和构建的时间,甚至不需要重新部署,随时替代 XML 文件,随时就可以更新。这很大程度上减低了维护和更新的复杂度。
XML 语言是易于解析和生成的,因此,易于 XML 语言描述 SWT 的界面设计工具,相较于基于 Java 代码的工具容易实现的多。同时,因为 XML 语言有严格而又有限的语法规则,所以也不会陷于用户对生成的 XML 进行各式各样的添加或更改,从而无法被工具识别的窘境。
基于不同界面技术的代码之间的转化是具有高度复杂性的,例如 Java Swing 和 SWT 描述的界面之间进行转化,甚至是 SWT 与 C# 界面之间进行转化。但如果二者同时使用 XML 作为其界面描述方式的话,情况就不同了。有了 XML 作为界面描述的中介,界面之间的转化就成为简单的事情了。因为不同标准的 XML 文档之间转化是易行的,更拥有 XSLT 等语言帮助实现 XML 文档之间的转化。如果客户已有应用的界面描述是基于 XML 或其他结构化文档描述的情况下,同时客户希望自动化将其转化为 SWT 界面并集成在富客户端应用程序中使用,那么使用 XML 描述的 SWT 界面就是一个绝佳的方案,文档之间的转化比代码之间的转化易行。
|
|
既然使用控制反转来创建 SWT 界面拥有如此多的优势,那么如何去做才能实现这种想法呢?
控制反转对装配 Java Bean 和 Bean 之间的依赖关系有成熟的方法,这在各种控制反转的实现中均有体现。我们所需要做的,只是将这种方法定制化,然后应用至 SWT 界面开发中而已。这里我们需要关注 SWT 控件与普通 Java Bean 的异同点,之后利用相同点,解决不同点,就可以实现控制反转在 SWT 界面开发中的应用问题。
先来看相同点,这是控制反转应用至 SWT 的契机。 SWT 的 API 非常友好,控件的属性基本都存在相对应的 get 和 set 方法,这与一般 Java Bean 的定制方式是相同的。基于这个共性,SWT 控件的一般属性都可以通过控制反转的属性注入方式,利用 Java 反射的原理,动态寻找并调用相应属性的 set 方法,将相应的属性注入到 SWT 控件实例中。这个共同点,是控制反转能够得于应用的关键点,仅此一点,就可以将大量属性设置的逻辑转化到 XML 属性配置中来。
现在了解一下不同点,SWT 与普通的 Java Bean 在处理上还是有很多不同的,我们逐一阐述:
SWT 控件的构造函数相较一般的 Java Bean 而言,是比较复杂的。复杂点存在于两个方面:SWT 控件的构造函数一般至少需要两个参数—父控件和风格;另一方面,父控件的引用无法通过定义 XML 获得,这个引用通常是在应用运行时才能拿到,例如父界面创建和界面环境初始化之后。
构造函数的复杂性问题,由于其中一个参数不能被 XML 定义初始化得到,所以也不能通过其他创建方式如工厂等模式来解决。这个问题是使用控制反转创制 SWT 界面的首要问题。解决这个问题,需要从几个方面入手:
- 使用包装类对 SWT 控件进行包装,包装类可以互相继承以实现逻辑的共享。包装类可以保持默认构造函数。对包装类的调用会转移为对被包装的控件实例的调用。
- 定制控制反转引擎,在初始化 SWT 控件时,不仅仅需要传入描述控件的 XML 文件,同时需要在运行时传入控件对应的父控件引用。换句话说,在用控制反转引擎初始化 SWT 界面元素时,同时传入父控件的引用。
- 延迟初始化控件和延迟注入属性。包装类可以有工厂方法能够创建出 SWT 控件的实例,但是,只有在父控件的引用被传入之后才能启动 SWT 控件创建的过程。同样,包装类可以接受对控件属性的注入并将这些注入重定向到对控件实例本身,但是注入属性的逻辑必须在 SWT 控件初始化之后才能启动。
基于以上几点,就可以解决因 SWT 构造函数复杂性导致控制反转无法应用的问题。与此同时,也能够收获很多额外的功能。
SWT 控件在客户场景中,很多时候不能满足应用需要,所以需要在控制代码中定制大量的事件处理和校验逻辑,例如文本框控件的最大长度限制,这就需要对文本框添加 监听器来解决。但是,如果我们发现最大长度属性是所有文本框的共有属性,希望在各个场合重用该属性,比如将该属性做成文本框控件的自有属性,希望通过直接 调用该文本框的方法,如 text.setMaxLength( “ 20 ” ),就可以重用最大长度的逻辑处理,省去添加监听器的复杂性,那么,我们直接能想到的实现方式,就是继承文本框控件,然后添加设置最大长度的方法。但是, 对 SWT 的文本框控件而言,这样做是不合适的。 SWT 几乎所有控件,都拒绝继承,因为每个控件的实现类中,均有 checkSubclass() 方法,避免开发人员对控件代码的恶意继承。那么,对控件类的包装,就成了非常推荐的做法。所以,通过对 SWT 控件的包装,可以不仅仅包装控件的创建逻辑,同时可以加入更多定制化的控件属性。
SWT 与 Java Swing 不同,SWT 控件之间的父子关系,是通过构造函数中父控件的传入而确定下来的。如何在控制反转的 XML 文件中,描述控件的父子关系呢?
最直观而又简单的描述方式,就是用标签的父子关系,描述控件的父子关系。 XML 是结构化的文档描述方式,每个标签均可以包含子标签。所以,当父标签表示成为控件时,子标签自然就可以表示成父标签的孩子控件。
如何进行控件之间父子关系的注入?这就需要从包装类上下文章。能够接受子控件的 SWT 控件包装类,可以开放出添加删除子控件的编程接口,那么,当控制反转引擎解析到子标签控件时,就可以调用相应接口,将初始化好的子控件添加到父控件中。
值得注意的是,延迟初始化在这里也会有应用。因为只有先创建出父控件,才能将父控件的引用传递给子控件,这样子控件的实例才能得以创建。所以,创建 和属性注入的过程应该是:父控件创建 -> 子控件创建 -> 子控件属性注入 -> 父控件属性注入。因为子控件本身,也是父控件的一种属性,需要调用父控件的添加子控件编程接口,进行子控件的注入。
XML 文档中,能描述的属性类型,只能是字符串类型。那么,如果控件属性需要的是其他的 Object 类型,例如颜色,SWT 控件接受的是 org.eclipse.swt.graphics.Color 作为其属性的参数,如何进行属性的注入呢?
这里可以利用转换器,将字符串转换为相对应的类型,然后再进行注入。以 Color 为例,在 XML 文件中,可以用 RGB 的数字来定义颜色,例如:” 255, 210, 210 ”,同时,在属性注入时,通过 Java 反射,得到希望注入的属性类型,如 org.eclipse.swt.graphics.Color,然后查找到该类型对应的转换器类,将字符串转化为需要注入的实例,进行属性的注入。
转换器的逻辑在很多控制反转引擎中均有实现,在 SWT 控件控制反转化的过程中,仅仅需要为 SWT 特定的某些参数类型编写转换器即可。例如:字体,颜色,图像等。
通过上述几点,控件的各种属性,和某些校验等业务逻辑,可以通过 XML 进行描述了。那么,复杂的事件处理怎么办?这里,我们仍然需要使用 Java 代码处理事件逻辑,并利用控制反转引擎进行注入。但是,在实现上,可以高度抽象,甚至可以做到,事件处理逻辑的接口,可以与界面技术无关。比如,同样的 XML 文件和事件处理代码,在 SWT 的控制反转引擎解析后,可以初始化 SWT 的图形界面,另一方面,也可以在 Swing 的控制反转引擎解析后,生成 Java Swing 的图形界面。
通过上述对 SWT 控件和普通 Java Bean 相同点的把握以及不同点的处理,就可以实现控制反转对 SWT 界面的创建了!下面章节我们可以看一些实现的例子,欣赏一下控制反转对 SWT 界面创建流程的天翻地覆的变化。
|
|
|
在这一章节中,我们以 IBM 的产品 BTT 为例,展示一下控制反转在 SWT 界面创建中的优雅之处。 BTT 的富客户端开发,不仅使用了 XML UI 作为其 SWT 界面表现的描述方式,同时提供了强大的工具支持,以可视化拖拽的形式,所见即所得的编辑基于 XML 的 SWT 界面,提高了 SWT 界面开发的效率,降低了 SWT 界面开发的入门门槛。
在这个示例章节中,我们希望创建出如下的登录界面,除了字体,颜色,排列对齐上的设置外,用户名的文本框,全长不得超过 8 个字符。
下面是使用 SWT 的 API 描述该界面的代码清单:
import org.eclipse.swt.SWT; import org.eclipse.swt.events.VerifyEvent; import org.eclipse.swt.events.VerifyListener; import org.eclipse.swt.graphics.Color; import org.eclipse.swt.graphics.Font; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Shell; import org.eclipse.swt.widgets.Text; public class Login { public static void main(String[] args) { final Display display = new Display (); Shell shell = new Shell (display); shell.setSize(400, 300); final Color YELLOW = new Color(display, 255, 255, 0); shell.setBackground(YELLOW); Label title = new Label(shell, SWT.NONE); title.setAlignment(SWT.CENTER); title.setBackground(display.getSystemColor(SWT.COLOR_BLACK)); title.setForeground(display.getSystemColor(SWT.COLOR_WHITE)); title.setFont(new Font(display, "arial black", 16, SWT.NORMAL)); title.setText("Login"); title.setBounds(80,15,140,30); Label lName = new Label(shell, SWT.NONE); lName.setText("User Name:"); lName.setBackground(YELLOW); lName.setBounds(30,55,80,20); Text tName = new Text(shell, SWT.BORDER); tName.setBounds(130,55,165,20); tName.addVerifyListener(new VerifyListener() { public void verifyText(VerifyEvent e) { if (((Text)e.widget).getText().length() >= 8) { e.doit = false; display.beep(); } } }); Label lPassword = new Label(shell, SWT.NONE); lPassword.setBounds(30,95,80,20); lPassword.setBackground(YELLOW); lPassword.setText("Password:"); Text tPassword = new Text(shell, SWT.PASSWORD | SWT.BORDER); tPassword.setBounds(130,95,165,20); Button bSubmit = new Button(shell, SWT.PUSH); bSubmit.setBounds(215,140,80,20); bSubmit.setText("Submit"); shell.open (); while (!shell.isDisposed ()) { if (!display.readAndDispatch ()) display.sleep (); } display.dispose (); } } |
BTT 使用 BTT Element Factory 作为控制反转的实现。如下是使用了 BTT 的 XML Ui 引擎初始化该 SWT 界面的 XML 清单:
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <XUI> <Composite background="255,255,0"> <Label bounds="80,15,140,30" background="0,0,0" text="Login" alignment="CENTER" font="arial black,16,NORMAL" foreground="255,255,255" /> <Label bounds="30,55,80,20" text="User Name:" background="255,255,0" /> <Text bounds="130,55,165,20" maxLength="8" /> <Label bounds="30,95,80,20" text="Password:" background="255,255,0" /> <Password bounds="130,95,165,20" /> <Button bounds="215,140,80,20" text="Submit" /> </Composite> </XUI> |
在 XML Ui 引擎的初始化定义文件中,我们会规定每个标签所对应的包装实现类以及各种属性的转换器,截取部分定义显示如下:
<map id="classTable"> <entry key="Composite" value="com.ibm.btt.rcp.xui.widgets.XUIComposite"/> <entry key="Text" value="com.ibm.btt.rcp.xui.widgets.XUIText"/> <entry key="Label" value="com.ibm.btt.rcp.xui.widgets.XUILabel"/> </map> <map id="propertyConverters"> <entry key="org.eclipse.swt.graphics.Image" value="com.ibm.btt.rcp.xui.converter.ImageConverter"/> <entry key="org.eclipse.swt.graphics.Color" value="com.ibm.btt.rcp.xui.converter.ColorConverter"/> <entry key="org.eclipse.swt.graphics.Rectangle" value="com.ibm.btt.rcp.xui.converter.RectangleConverter"/> <entry key="org.eclipse.swt.graphics.Font" value="com.ibm.btt.rcp.xui.converter.FontConverter"/> </map> |
通过上面两段 XML 描述,可以验证上一章节中描述的大部分思想:
- 通过 XML 文件中的标签,描述需要创建并初始化的控件,例如 <Composite> 标签用以初始化 com.ibm.btt.rcp.xui.widgets.XUIComposite 控件。每个标签,对应的是控件的包装类。
- 包装类的种类,可以根据用户和业务的需要添加,更改和定制。同时,这些包装类,经过扩展,不仅仅可以支持 SWT 的控件,也可以支持例如 Swing 等其他 Java 界面展示的控件,因为在 BTT 的 XML UI 中,包装器控件都是高度抽象的。
- 控件的包装类不仅可以重定向设置 SWT 控件的一般属性,也可以包含 SWT 控件可定义属性之外的其他属性,用以重用某些业务逻辑。例如 Text 控件的最大长度属性,这是最简单的也是最容易描述该场景的属性。如果有对文本控件最大长度的限制,仅需要将相应的逻辑抽取并定义在包装类中,同时公开该属 性的设置方法即可。
- 通过 XML 文档标签之间的父子关系,定位控件之间的父子逻辑。例如,Composite 标签和 Label 标签之间的父子关系。
- 通过标签的属性定义,描述控件的相应属性,例如以 Label 标签的 background 属性来描述标签控件的背景色属性。
- 使用转换器,可以将 XML 文档中的字符串定义自动转化为 SWT 控件所需要的各种对象类型,例如 ColorConverter 。转换器的种类,可以根据用户包装类的需要进行扩展。
BTT XML UI 技术,实现了本文中阐述的基于控制反转创建 SWT 用户界面的构想,拥有了:易于理解的用户界面描述,简洁的业务逻辑代码,易于更新部署和维护,易于与其他基于文档的界面技术之间相互转化等诸多优点。同 时,BTT XML UI 作为面向银行前端的用户界面编辑框架,还包含如下不可忽视的优势:
使用控制反转注入业务逻辑,将用户界面与业务逻辑分离开来,并使用 XML 和 Java 代码进行描述,使二者都能做到模块化,供其他应用场景重用。
BTT XML UI 在包装器类中加入了大量的银行相关属性和逻辑,便于开发银行前端界面。
BTT XML UI 提供了页面流程框架,通过 BTT Processor 流程处理器,可以将不同的 XML 用户界面串联为一支完整交易,并在不同的交易页面流程中重用不同的 XML 用户界面。同时,提供了基于页面流程的数据共享和生命周期管理。这使得页面流的技术能够实现在 eclipse 的富客户端应用中来。
由于使用了 XML 作为界面描述的载体,无论界面的解析还是生成都化复杂为简单。 BTT XML UI 不仅提供了强大的界面解释引擎,更基于 XML 的文档格式,提供了高效的开发工具支持。用户可以仅仅通过拖拽、属性编辑等可视化的方式,所见即所得的开发期望的用户界面。同时支持运行调试和断点的功 能,使用户即刻体验到自己正在开发的界面,包括业务逻辑和事件监听。
下图既是 BTT XML UI 编辑器的截图,该编辑器为 XML 界面开发提供了强大且高效的工具支持。同时,正在开发中的界面也能够展示出 XML 可描述的 SWT 的界面的复杂性。
|
|
控制反转创建 SWT 界面,不仅仅能带来 IT 领域的巨大优势,同时,在业务领域之内,在某些用户场景之中,更能够体现其价值。下面以银行业的某些典型场景为例,看一下 XML 文档的描述方式,带给客户的便利。
银行业为了控制风险,在柜员系统中有授权的操作。当大额取款等高风险操作出现时,需要主管的授权才能继续。目前的银行操作中,授权分为两种:本地授 权和远程授权。本地授权,顾名思义,就是由主管本人到柜员的系统边,输入授权密码或者刷一下主管授权的磁卡,使交易能够获得审批继续进行。远程授权,就是 利用 IT 系统的能力,将交易数据远程发送给主管,然后主管直接在自己的业务系统上审批即可,无需走到柜员身边即可批准相应交易。本地授权在某些方面,相较远程授权 有劣势:主管必须和柜员在同一网点办公;主管需要花费大量时间穿梭于柜员之间;客户为了继续交易需要等待主管的到来,客户体验不佳。而远程授权,可以另主 管在远程的办公地点办公;多个网点可共享同一主管;节省大量穿梭时间;客户体验会比较好,但是,如何保证授权的安全性是远程授权需要处理的问题。
当银行系统希望支持远程授权时,就需要将柜员的交易信息准确的传递给审批主管,这时,基于 XML 文档的 SWT 界面描述就有了用武之地。准确的交易信息传递,最佳方案就是原封不动的将交易界面在远程系统中呈现出来,而 XML 描述的界面,因其描述文件流非常小巧,在不同终端之间传递时,在银行这种带宽要求高的环境下非常适用。为了重现交易界面,只需要将 XML 文件的描述流和当前页面数据同时传递到远程系统,既可以通过 XML UI 引擎将交易场景完美重现,从而完成对远程授权的功能实现。
银行系统需要将交易日志记录到数据库中,供业务人员审核和查看。与远程授权的场景类似,当查看历史交易数据时,拥有重现当时的交易场景的需求。这 时,仅需要将 XML 用户界面的描述文件流保存至数据库,然后将界面文件流的数据库表与交易历史数据表建立关联,那么,当查询历史日志时,就可以重现当时的交易场景,从而满足 银行对电子日志查询的多样化需求。
同时,银行系统也有复核的需求,场景是在复核交易时,将所需校验的关键数据空出来,然后由复核人员输入一次,看与历史的交易数据是否一致。这种交易 复核的需求,也可以由 XML 用户界面实现。在查看电子日志时,可以将重现交易界面的过程定制一下,使某些数据域隐藏,然后由复核人员手工输入,提交后再与隐藏数据域对应的交易历史数 据进行比较,反馈出复核结果。
|
|
基于控制反转的思想,创建 SWT 界面,使界面的复杂代码逻辑,有了简洁易懂的承载方式— XML 文档。通过 XML 这一业界标准的、有广泛用户群体和大量工具框架支持的描述语言,使 SWT 的界面描述萌发出更多的生机,带来了很多决定性的优点,必将令 SWT 在各种项目和客户场景中,应用的更加广泛。
本文基于 IBM 的银行业产品 BTT 出发,阐述了控制反转的思想对 BTT 富客户端应用带来的变化,同时描述了对几个当前银行业典型场景的应用。这仅仅是冰山一角,读者可以延续这种思想,多多思考,如何将 XML 的富客户端界面技术应用到各个行业的更多用户场景,满足客户的多种需要。
- 参考 Eclipse SWT 项目主页。
- 参考控制反转的文章:Inversion of Control Containers and the Dependency Injection pattern 。
- 参考 BTT 的 IoC 容器:BTT Element Factory 配置简洁的依赖注入容器 。
- 参考 BTT 的页面流控制框架:通用页面流程框架及实例介绍 。
- 查看 IBM BTT Information Center : 了解更多关于BTT产品的信息。
- 查看 IBM BTT Education Assistant :了解更多关于BTT使用方面的介绍。
- 访问 developerWorks 开放源码专区 ,获得丰富的 how-to 信息、工具和项目更新,帮助您用开放源码技术进行开发,并与 IBM 产品结合使用。
| 王浩,任职于 IBM 中国软件开发中心,目前主要负责 eclipse 插件技术相关的开发工作,您可以通过 allenwang@cn.ibm.com 与他联系。 |