2008-05-17

动态属性方案

改行了,不再做软件开发了,之前工作中做过的一些有价值的东西陆续发布在这,希望对其他人有用。

(图片看不到的话,请下载打包了文档和代码的附件^^)
------------------------------------------------------------
动态属性方案说明

方案简介:
一般情况下,最终用户可操作存取的数据范围受限于预先定义或编码的数据库表字段及Java Model类的属性声明。动态属性方案让用户得以突破这些限制,可以动态增删属性或字段,对之编辑并存取。
方案可以分为两部分,一部分是使普通JavaBean具有动态属性的特性;一部分是提供对这些动态属性的界面编辑及持久化的支持。

实现说明:
一、使普通JavaBean具有动态属性特性
改造普通JavaBean,使之具有动态属性特性的职责,由接口DynamicBean及其实现类DynamicBeanImpl承担。只需轻微调整普通JavaBean的代码,即可使其获得动态属性的特性,同时保持原有特性不变。
DynamicBean和DynamicBeanImpl提供如下两种改造方式:

<图片1>

1)改造方式1的示例代码如下:
1)/**
2) * 通过继承机制直接获得动态属性特性的扩展类
3) * @author Tu_Minglei
4) */
5)public class MyTestBean extends DynamicBeanImpl {
6) private Long id;
7) private String name;
8) private Object value;
9)
10) public Long getId() {
11) return id;
12) }
13) public void setId(Long id) {
14) this.id = id;
15) }
16) public String getName() {
17) return name;
18) }
19) public void setName(String name) {
20) this.name = name;
21) }
22) public Object getValue() {
23) return value;
24) }
25) public void setValue(Object value) {
26) this.value = value;
27) }
}
2)改造方式2的示例代码如下:
1)/**
2) * 通过接口+聚合机制获得动态属性特性的扩展类
3) * @author Tu_Minglei
4) */
5)public class MyTestBean2 implements DynamicBean,Map {
6) private Long id;
7) private String name;
8) private Object value;
9)
10) public Long getId() {
11) return id;
12) }
13) public void setId(Long id) {
14) this.id = id;
15) }
16) public String getName() {
17) return name;
18) }
19) public void setName(String name) {
20) this.name = name;
21) }
22) public Object getValue() {
23) return value;
24) }
25) public void setValue(Object value) {
26) this.value = value;
27) }
28)
29) @Override
30) public String toString(){
31) return "[id:"+id+",name:"+name+",value:"+value+"]";
32) }
33)
34) /**++++++++++++++++++++++++++++++++++++++++++++++++++++++
35) * 说明:以下代码可以原封不动的拷入目标类中
36) **++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
37) DynamicBeanImpl _dynamicStub = new DynamicBeanImpl(this);
38) public Object get(String propName) {
39) return _dynamicStub.get(propName);
40) }
41) public void set(String propName, Object value) {
42) _dynamicStub.set(propName, value);
43) }
44) public void declare(String propName, Class propType) {
45) _dynamicStub.declare(propName, propType);
46) }
47) /**---- 注:如果不需要实现Map接口,下列代码可以不拷入目标类中 ----*/
48) /**--------------- for Map Implementation ---------------*/
49) public Object get(Object key) {
50) return _dynamicStub.get(key);
51) }
52) public Object put(Object key, Object value) {
53) return _dynamicStub.put(key, value);
54) }
55) public void putAll(Map t) {
56) _dynamicStub.putAll(t);
57) }
58) public Object remove(Object key) {
59) return _dynamicStub.remove(key);
60) }
61) public void clear() {
62) _dynamicStub.clear();
63) }
64) public boolean containsKey(Object key) {
65) return _dynamicStub.containsKey(key);
66) }
67) public boolean containsValue(Object value) {
68) return _dynamicStub.containsValue(value);
69) }
70) public Set keySet() {
71) return _dynamicStub.keySet();
72) }
73) public Collection values() {
74) return _dynamicStub.values();
75) }
76) public Set entrySet() {
77) return _dynamicStub.entrySet();
78) }
79) public boolean isEmpty() {
80) return _dynamicStub.isEmpty();
81) }
82) public int size() {
83) return _dynamicStub.size();
84) }
}

注:DynamicBeanImpl同时实现了DynamicBean和Map接口。

有关这两种改造方式的完整样例代码及其测试用例,请查看com.ctic.core.prod.common.extproperty. DynamicBeanImplTest.java。

二、对这些动态属性的界面编辑及持久化的支持
对动态属性的定义信息及数据信息的存取,以及编辑界面的生成的职责,由扩展属性框架承担。
扩展属性框架(以下简称为:框架)提供如下存取机制:
1)首先,用户通过框架预先为指定对象关联一些属性定义信息;
2)以后,当用户传入指定对象(已实现DynamicBean接口)要求保存时,框架将按照预先定义的信息提取相应的属性数据保存下来;
3)接着,当用户传入指定对象要求装填相关属性数据时,框架将能够把原先保存的数据按照属性说明的要求填入该对象中。
当用户传入指定对象,要求获得相应的编辑面板时,框架可以根据用户预先关联的属性定义信息,生成编辑面板。
框架的基本结构及对外接口如下图所示:

<图片2>

相关说明:
1)用户将通过DynamicPropertyService服务接口存取属性定义信息并和目标对象关联;
2)用户将通过DynamicPropertyService服务接口或者相应的PropertyDataBO存取和目标对象关联的属性数据信息;
3)用户将通过DynamicPanelManager服务类获得相应的编辑面板。

关于框架在:1)属性定义信息和目标对象关联;2)对目标对象的动态属性数据存取;3)动态属性编辑面板的生成,等方面的实现细节,请参阅相关的Rose设计文档及源代码,在此不作累述。

注1:框架内部根据目标对象的特征信息,来保持和所托管信息的匹配。不同对象类型有不同的特征信息,而方案只预置了对一部分目标对象的支持。
注2:相关的Rose设计文档我已上传到svn的ctic-doc\设计文档\Rose设计目录下。相关的源代码也已上传到svn上。


使用要点:
为了有效使用扩展属性框架,用户需要做出以下调整:
1)调整目标Model,以使其具有动态属性特性(注:如果框架用到的工具类KeyObjectUtils还没有对该对象类型提供支持,则还要加入相应的支持代码);
2)用户预先把相应的属性定义信息和目标对象关联;
3)用户BO或Service在存取目标对象的过程中,加入相应的对动态属性服务的调用代码(注:为了使框架能提取到有用的特征信息,用户应保证在调用之前,Id值不为NULL);
4)用户在客户端,加入调用动态面板管理器获得相应的编辑面板的代码,以及其他动态属性相关的处理代码。

潜在应用:
由于DynamicBean和DynamicBeanImpl的相对独立性,使得这两个接口/类除了用于需要存储的动态属性之外,还可以存放一些不需存储的临时属性,像:和具体Model对应的VO中的属性,动态查询中临时使用的查询参数字段,标识内存中Model对象的操作状态(insert、update、delete),等等。

注:为了使DynamicBeanImpl能充当动态查询语句中的万能参数对象的角色,该类特意实现了java.util.Map接口。用户只需把SQLMap中相应查询语句的传入参数的类型改为java.util.Map即可,其他地方可以仍旧把它当作原来的Model。
评论
tminglei 2008-05-18
这个方案有两处地方值得一看:
1)一处是已经独立发布了的“可以给Javabean添加动态属性特性的工具类”;
2)另一处就是根据属性配置信息生成控件元素并自动布局的前端工具类。
发表评论

您还没有登录,请登录后发表评论

tminglei
搜索本博客
最近加入圈子
最新评论