- 浏览: 1598168 次
- 性别:
- 来自: 杭州
文章分类
最新评论
-
jsrgzhangzhiyong:
关于null值的转换还是感觉不太友好,就像 mapstruct ...
我也造了个轮子:BeanMapping(属性拷贝) -
he037:
a417930422 写道引用使用EPHEMERAL会引出一个 ...
基于zookeeper的分布式lock实现 -
seancheer:
qianshangding 写道首先节点启动后,尝试读取本地的 ...
zookeeper学习记录三(session,watcher,persit机制) -
雪夜归人:
您好,我想咨询一下,开源的canal都能支持mysql的哪些版 ...
Canal BinlogChange(mysql5.6) -
zhoudengyun:
copy 一份做记录,后续学习,请知悉
阿里巴巴开源项目: 基于mysql数据库binlog的增量订阅&消费
背景
最近公司在大力推进服务化平台,我在中间主要做一个orm框架,解决model和数据源之间的映射问题。这里不选择已有的hibrenate,主要考虑自己公司的一些特殊场景:比如多数据源(数据库,搜索引擎,memcached,nosql等),同时可以 做一些特殊优化,比如多数据源加载时采用并行加载(我之间做的一个工具包 (业务层)异步并行加载技术分析和设计)
也不多罗嗦,我主要负责从多个数据源搜集回来的数据,构造成对应的model对象。可以看一下具体的分析过程。
分析
每个数据源采集回来的数据可能比较凌乱,有map对象,POJO对象,至于这个映射过程。因为是在老系统上实施,以前都没有service的概念,在数据库的设计会很比较乱,都是来一个需求加几个字段的那一类型。 所以具体data -> model对象的映射过程,就需要额外考虑一些特殊功能。
需求整理:
- 处理的data是个map对象
- 处理的data是个pojo bean
- 映射过程中,处理的data属性名和目标对象model的属性会大不相同
- 映射过程中,data中的数据大多都是文本型,而对应的model会是根据业务场景定义的强类型,需要有类型转化
- 对应的data可能是一个平面型的map/bean对象,需要转化有层次结构,带立体的模型。比如model里包含一些子model等
- 需要处理特殊情况,比如data中有个属性是个json格式数据,需要在解析后再转化到某几个model属性上
设计
根据上面的需求分析,因为要解决不同属性名自己的映射关系,单纯的依赖bean属性的扫描无法满足。所以需要引入配置文件,定义mapping的映射关系。
整体设计示意图:
说明:
- 将属性mapping的动作抽象成Get / Set两个操作。 Get操作针对数据源对象,Set操作针对数据目标对象
-
在Get/Set中间,定义了一个ValueProcess处理插件的概念,允许扩展相关的功能插件 (自认为相比于BeanUtils/BeanCopier的非常好的亮点,扩展性良好)
1. 比如默认值
2. 类型转化器
3. json数据处理
4. 日志记录
对应的类关系图:
Get/Set操作类
ValueProcess设计类:
客户端使用类设计:
- BeanMapping : 本轮子的核心功能,通过基于配置方式的mapping映射,支持convetor,defaultValue,script的所有功能。要求使用之前必须提前配置bean-mapping映射。
- BeanCopy 和 BeanMap : 都是一些扩展功能,基于本轮子的核心架构不变的基础上,开发了BeanUtils.copyProperties() , BeanUtils.describe, BeanUtils.populate()的功能。 使用该api,可以不需要配置映射文件,会进行自动扫描,就是基于同名属性的处理前提。
- BeanMappingUtil : 提供了BeanMapping , BeanCopy , BeanMap的所有方法,提供静态的util方法处理。每次都会构造对应的BeanMapping等对象,注意:每次进行构造BeanCopy,BeanMap,解析的属性结果会有cache。所以使用该util不会有很明显的性能下降,无非就是多一些临时对象。
最后定义的配置文件示例: mapping.xml
<bean-mappings xmlns="http://mapping4java.googlecode.com/schema/mapping" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://mapping4java.googlecode.com/schema/mapping http://mapping4java.googlecode.com/svn/trunk/src/main/resources/META-INF/mapping.xsd"> <!-- (bean-bean) mapping 测试 --> <bean-mapping batch="true" srcClass="com.agapple.mapping.object.SrcMappingObject" targetClass="com.agapple.mapping.object.TargetMappingObject" reversable="true"> <field-mapping srcName="intValue" targetName="intValue" /> <field-mapping targetName="integerValue" script="src.intValue + src.integerValue" /> <!-- 测试script --> <field-mapping srcName="start" targetName="start" /> <field-mapping srcName="name" targetName="targetName" /> <!-- 注意不同名 --> <field-mapping srcName="mapping" targetName="mapping" mapping="true" /> </bean-mapping> <bean-mapping batch="true" srcClass="com.agapple.mapping.object.NestedSrcMappingObject" targetClass="com.agapple.mapping.object.NestedTargetMappingObject" reversable="true"> <field-mapping srcName="name" targetName="name" defaultValue="ljh" /> <!-- 测试default value --> <field-mapping srcName="bigDecimalValue" targetName="value" targetClass="string" defaultValue="10" /> <!-- 测试不同名+不同类型+default value --> </bean-mapping> </bean-mappings>
说明:
- bean-mappings : 可以指定xsd,方便编写配置文件。通过IDE可以给于提示
- bean-mapping : 定义需要进行mapping映射的对象信息,需要指定class全路径
reversable主要表明此mapping动作是可逆的,默认为true。 batch主要是一优化特性,后面再细表。 -
field-mapping : 主要定义需要进行映射的属性之间的映射关闭
srcName : 源对象的属性名
srcClass : 源对象的class类型
targetName : 目标对象的属性名
targetClass : 目标对象的class类型
mapping : 表明是否需要进行递归映射,比如这里的,在处理NestedSrcMappingObject和NestedTargetMappingObject时,会递归进行映射处理
defaultValue : 很好理解,就是针对源属性为null时,默认值处理
convetor : 自定义类型转化器 (默认支持基本类型,BigDecimal,BigInteger,Array,List之间的转化处理)
script : 高级特性,支持自定义的映射规则,比如这里进行一个+运算。
targetName="integerValue" script="src.intValue + src.integerValue"
几点说明:
- srcClass/targetClass: 默认可不关注,系统会自动进行识别,在defaultValue和convetor转化处理。 还有一点:如果对象中出现同名的属性时,可以指定targetClass进行唯一定位
- defaultValue : 相比于BeanCopier和BeanUtils,一个特有的特性。 大家熟悉ibatis的配置就知道会有一个nullvalue配置,主要是方便客户端处理,避免进行一些无谓的==null/==0这样的处理
- convetor : 相比于BeanUtils, 这里允许声明属性之间的转化类,比如你注册了一个alias别名的convetor,就可以在这里声明进行使用,会优先使用你定义的(如果不指定,则会进行自动根据类型进行匹配)。
自动处理会有个局限性,就是convetor会是全局性。比如你定义了一个String到Date的处理,以后整个jvm中所有的场景都会按照你定义的进行转化,到时候你怎么死自己都不知道 - script: 系统的高级特性,做为系统的一些扩展点,可以支持一些比较复杂的处理,比如以后的json/xml等处理,只需注册你的functions。比如这里定义: script="src.intValue + src.integerValue"。
BeanMapping列子: BeanMappingTest.java
public BeanMapping srcMapping = BeanMapping.create(SrcMappingObject.class, TargetMappingObject.class); public BeanMapping targetMapping = BeanMapping.create(TargetMappingObject.class , SrcMappingObject.class); @Test public void testBeanToBean_ok() { SrcMappingObject srcRef = new SrcMappingObject(); srcRef.setIntegerValue(1); srcRef.setIntValue(1); srcRef.setName("ljh"); srcRef.setStart(true); TargetMappingObject targetRef = new TargetMappingObject();// 测试一下mapping到一个Object对象 srcMapping.mapping(srcRef, targetRef); SrcMappingObject newSrcRef = new SrcMappingObject();// 反过来再mapping一次 targetMapping.mapping(targetRef, newSrcRef); }
BeanCopy例子: (发觉和BeanCopier使用比较像) BeanCopyTest.java
public BeanCopy srcCopyer = BeanCopy.create(SrcMappingObject.class, TargetMappingObject.class); public BeanCopy targetCopyer = BeanCopy.create(TargetMappingObject.class , SrcMappingObject.class); @Test public void testCopy_ok() { SrcMappingObject srcRef = new SrcMappingObject(); srcRef.setIntegerValue(1); srcRef.setIntValue(1); srcRef.setName("ljh"); srcRef.setStart(true); TargetMappingObject targetRef = new TargetMappingObject();// 测试一下mapping到一个Object对象 srcCopyer.copy(srcRef, targetRef); SrcMappingObject newSrcRef = new SrcMappingObject();// 反过来再mapping一次 targetCopyer.copy(targetRef, newSrcRef); }
BeanMap例子: (支持bean<->map的转化处理) BeanMapTest.java
public BeanMap beanMap = BeanMap.create(SrcMappingObject.class); @Test public void testDescribe_Populate_ok() { SrcMappingObject srcRef = new SrcMappingObject(); srcRef.setIntegerValue(1); srcRef.setIntValue(1); srcRef.setName("ljh"); srcRef.setStart(true); NestedSrcMappingObject nestedSrcRef = new NestedSrcMappingObject(); nestedSrcRef.setBigDecimalValue(BigDecimal.ONE); srcRef.setMapping(nestedSrcRef); Map map = beanMap.describe(srcRef); SrcMappingObject newSrcRef = new SrcMappingObject();// 反过来再mapping一次 beanMap.populate(newSrcRef, map); // 从map属性设置到bean }
性能测试数据
不过前面功能说的如何天花乱坠,整个工具的性能相比也是大家比较会关注的一个点。 我这里大致做了下测试:构造一个CopyBean,基本涵盖了普通类型,对象处理等,进行批量处理
CopyBean :
public class CopyBean { private int intValue; private boolean boolValue; private float floatValue; private double doubleValue; private long longValue; private char charValue; private byte byteValue; private short shortValue; private Integer integerValue; private Boolean boolObjValue; private Float floatObjValue; private Double doubleObjValue; private Long longObjValue; private Short shortObjValue; private Byte byteObjValue; private BigInteger bigIntegerValue; private BigDecimal bigDecimalValue; private String stringValue; }
BeanCopy性能测试
对比的内容:
- BeanCopy.copy
- BeanCopy.simpleCopy (不做类型转化)
- Method.invoke
- FastMethod.invoke
- BulkBean
- BeanCopier
- HardCode (硬编码,直接手工挨个复制属性)
- PropertyUtils (不做类型转化)
- BeanUtils
开启batch优化(200w次):单位ns | 纯解释执行(排除JIT优化)(10w次):单位ns | |
BeanMapping.copy | 1189 | 72780 |
BeanMapping.simpleCopy | 1178 | 69381 |
Method | 1322 | 25882 |
FastMethod | 533 | 15961 |
BulkBean | 108 | 4420 |
BeanCopier | 18 | 1566 |
HardCopy | 17 | 1376 |
PropertyUtils | 22143 | 1037770 |
BeanUtils | 43980 | 1766392 |
- 首先注意一下,单位是ns。 1s = 1000ms = 1 * 10^9 ns
- BeanCopier和手工编码写的copy性能基本接近
- BeanMapping的copy和simpleCopy的区别,copy可以支持类型转化,simpleCopy不会处理类型转化。
- BeanMapping的性能是BeanUtils的近40倍左右,不过和BeanCopier还是有些差距,大概在50倍左右。 (换另一个概念,就是执行100w次,BeanCopier可以比BeanMapping节省1秒,可以比BeanUtils节省40多秒,比较直观吧)
最后
整个过程,完成功能代码大概只花了一周的时间,但是代码的重构/抽取,性能优化花了我近2周的时间。性能从最初的比BeanUtils慢,逐步的提升到了快几十倍,还是比较有成就感的。
还有一点,就是自己比较满意ValueProcess概念的设计,相比于BeanCopier或者BeanUtils扩展性好多了,比如自身系统的功能:日志记录,默认值,类型转化,script脚本(EL表达式)。都是通过扩展接口实现,也比较方便切换成不同的实现.。
有兴趣的同学,可以看下googlecode上的代码,有问题欢迎联系!
googlecode地址 : http://code.google.com/p/mapping4java
相关功能测试代码:
BeanCopyTest.java
3.1 KB
BeanMapTest.java
2.1 KB
BeanMappingTest.java
7.8 KB
ConfigTest.java
1.7 KB
ConvertorTest.java
8.5 KB
ScriptExecutorTest.java
2.2 KB
ScriptTest.java
2.7 KB
性能测试代码:
CopyPerformance.java
12.9 KB
MapPerformance.java
3.0 KB
需求搜集
结合了dozer的一些特性,也顺便整理了一下自己的后续action的一些功能点,做了适当取舍。
评论
对于要往数据库存不能存null的情况,虽然mapstruct也提供了defaultvalue,还是得自己去配置, mapstruct可以通过改源码支持注解defautlvalue,解决每次都要配置的问题,这个组件是否可以在这里优化下?
1.对于FastMethod ,PropertyGetExecutor 类
public Object invoke(Object obj) throws BeanMappingException {
try {
return (method == null ? null : method.getJavaMethod().invoke(obj, (Object[]) null));
} catch (Exception e) {
throw new BeanMappingException(e);
}
}
为何method.getJavaMethod().invoke(obj, (Object[]) null)),而不直接使用
method.invoke(obj, (Object[]) null))?
2.对于所有实现ValueProcess,对于默认值ValueProcess,可否将源字段为空情况下,直接取默认值。
第一个问题:目前最新的版本就是做method.invoke(), [https://github.com/alibaba/tamper/blob/master/src/main/java/com/alibaba/tamper/core/introspect/FastPropertyGetExecutor.java]
2. 第二个问题没太看明白,默认值不就是针对源字段值为null的时候取默认值的么?
1.对于FastMethod ,PropertyGetExecutor 类
public Object invoke(Object obj) throws BeanMappingException {
try {
return (method == null ? null : method.getJavaMethod().invoke(obj, (Object[]) null));
} catch (Exception e) {
throw new BeanMappingException(e);
}
}
为何method.getJavaMethod().invoke(obj, (Object[]) null)),而不直接使用
method.invoke(obj, (Object[]) null))?
2.对于所有实现ValueProcess,对于默认值ValueProcess,可否将源字段为空情况下,直接取默认值。
有需求可以提
这个优化直接使用了cglib的BulkBean的处理,可以增加jvm property设置dump路径.
System.setProperty(“cglib.debugLocation”, "/tmp/cglib");
具体get/set batch处理类: com.agapple.mapping.core.introspect.PropertyBatchExecutor.
因为cglib的字节码优化已经处理的差不多了,也就没去折腾使用javasist手写一遍字节码处理.
简单的过了下orika的useGuide
- http://code.google.com/p/orika/wiki/GettingStartedGuide
可以看下BeanMapping.
useGuide : http://code.google.com/p/mapping4java/wiki/UserGuide
programGuide : http://code.google.com/p/mapping4java/wiki/ProgramGuide
自认为会比orika更加容易扩展,核心的概念就3个,GetExecutor/SetExecutor/ValueProcess,都可以进行相应的扩展完整一些自定义.
BeanMapping是在我们公司的一个重构项目中使用,大致业务就是将原先基于数据库表设计的service,完全转化为按领域模型的设计,中间就有对原先的平级的DataObject转化为多级的Domain Object,里面的逻辑可想而知.
至于性能上,理论上来说和orika不会有很大的差别,大家都是在一个起跑线上
这里有几个问题想和楼主交流下:
1. 既然是用字节码增强去做了”合并多次的get/set请求生成字节码调用“, 其实可以更进一步, 直接生成类似手动代码的 get set 方法字节码, 在运行期完全不做相关字段的类型;
2. com.agapple.mapping.core.process.proceed 方法是个递归方法, 虽然楼主做了优化, 成了尾递归, 但是对于尾递归的优化, 不同的JVM 实现, 不同JDK 版本, 那些版本做了优化还是需要查看下的, 这个可能在某些JVM 上是个大坑, 很容易掉进stackoverflow 的坑里面。
目前在对象拷贝和转换这块, 功能上做的最好的应该是Dozer, 但是性能很差劲, 一大堆运行期反射去查看class type, field type...
性能上做的最好的是Orika, 这个可以参考 我的博文http://wangbt5191-hotmail-com.iteye.com/blog/1632444 对它的实现原理的探讨和它的官方站点
https://code.google.com/p/orika/
com.agapple.mapping.core.process.proceed 递归方法调用并不在get/set字节码处理的优化中,它只是解决扩展插件的功能 (比如添加默认值,类型转化,el表达式支持等)。,如果单存追求速度,可以关闭扩展功能。
之前看过dozer的feture,BeanMapping做的这个功能不会比它少,而且在扩展性上胜他许多,具体性能测试没对比过,不过做过BeanMapping和BeanUtils的对比,大概是在20~40倍的差距。
这里有几个问题想和楼主交流下:
1. 既然是用字节码增强去做了”合并多次的get/set请求生成字节码调用“, 其实可以更进一步, 直接生成类似手动代码的 get set 方法字节码, 在运行期完全不做相关字段的类型;
2. com.agapple.mapping.core.process.proceed 方法是个递归方法, 虽然楼主做了优化, 成了尾递归, 但是对于尾递归的优化, 不同的JVM 实现, 不同JDK 版本, 那些版本做了优化还是需要查看下的, 这个可能在某些JVM 上是个大坑, 很容易掉进stackoverflow 的坑里面。
目前在对象拷贝和转换这块, 功能上做的最好的应该是Dozer, 但是性能很差劲, 一大堆运行期反射去查看class type, field type...
性能上做的最好的是Orika, 这个可以参考 我的博文http://wangbt5191-hotmail-com.iteye.com/blog/1632444 对它的实现原理的探讨和它的官方站点
https://code.google.com/p/orika/
hi,地址没错,可能你得翻个墙了
第二个确实错了 你复制出来看下
多谢指出, 多了个%20,已经修正。
hi,地址没错,可能你得翻个墙了
第二个确实错了 你复制出来看下
下载:
svn checkout http://mapping4java.googlecode.com/svn/trunk/ mapping4java
or
http://code.google.com/p/mapping4java/downloads/list
编译:
mvn clean install eclipse:eclipse
谢谢了,昨天公司check不下来。。。 在家里居然可以
下载:
svn checkout http://mapping4java.googlecode.com/svn/trunk/ mapping4java
or
http://code.google.com/p/mapping4java/downloads/list
编译:
mvn clean install eclipse:eclipse
你描述的两个业务场景,基本上也就是我们现在遇到比较多的。只不过我们现在大范围进行重构,构建SOA服务时,第2个场景的问题就特别明显
OK,扯上了SOA,那就应该考虑叫做xmlbeanMapping更有用武之地,跟XMLBeans之流的对着干
有时候我倒是怀念起ETL
呵呵,兄弟,别这么较真么。
就和你用spring一样,虽然它大部分也是用xml配置,同样你也可以使用api方式和annotation,这个是每个开发者自己的选择。
xml只是目前的一种配置方式,后续是马上有计划实施api,annotation的配置。
哈哈,其实我是在使劲的想到底什么场景可运用
然后你提到了SOA,我就感慨了一下,无意跟你较真
大家都在分享对吧,这很宝贵——我是很希望你仔细给大家点场景提示
这个一开场,具体的背景介绍就提到了一个比较大的使用场景。
目前公司的几个场景:
- model 和 DO的转化 (DO = Data Object , 数据库对象的设计是一种大宽表的设计,domain/model的设计,会有层次结构&具体)。 比如表设计存储会采用json存储动态数据,而在model中会是具体的属性
- model 和 VO的转化 (VO = View Object , 公司的产品detail页面,涉及了后端n多个domain/model的组合展示,这时候会进行包装成VO,包装一些页面组装逻辑)
- model 和 DTO的转化 (DTO = Data Transfer Object ,公司子系统比较多,系统之间会有比较多的rpc等remote调用)
- form -> bean的转化 (现在流行的几个MVC框架,都已经开始支持view层的参数注入,比如@Paramter(name="field")String , @Form("name=xx")Bean)。 提交的form表单数据,基本都是以map+list为主,就会涉及一个mapping
其他的有些场景,更多的会是系统重构引起的,为支持兼容性,会考虑将接口的model,mapping映射到新的domain/model上。 这样的场景如果是做产品维护的比较会有体会
annotation 消除起来很麻烦 比如有很多地方用了annotation 但发现有几个地方不是很合适,想去掉。。。或者引入了别人对我没有用的annotation包...
xml看起来比较直观,容易差错,作为一种配置可以很方便的被修改,个人倾向于xml
基本认同观点。 普遍的场景还是倾向于xml。
针对几个场景:form bean校验,数据库事务等。倾向于使用annotation,因为配置和java代码是一个整体的描述
你们淘宝带代码出来看起来还是蛮开放的。。。不像我们,不管涉不涉及业务,是代码就带不出来。。。
确实插件化的设计还是很赞的,另外用script在xml里面,我们的项目里也有用,感觉表达能力很强,很好。
从哪里看出有淘宝的信息? 呵呵,我非淘宝人员
可以这么说,代码是你自己写的。只不过用在公司的某个项目上而已
我们一般也会要求,涉及公司信息的代码或者信息不能在blog里讨论
来自杭州。。我经验主义了。。呵呵
哈,阿里系的公司都是在杭州的哦。而且混这里的人很不少
annotation 消除起来很麻烦 比如有很多地方用了annotation 但发现有几个地方不是很合适,想去掉。。。或者引入了别人对我没有用的annotation包...
xml看起来比较直观,容易差错,作为一种配置可以很方便的被修改,个人倾向于xml
你描述的两个业务场景,基本上也就是我们现在遇到比较多的。只不过我们现在大范围进行重构,构建SOA服务时,第2个场景的问题就特别明显
OK,扯上了SOA,那就应该考虑叫做xmlbeanMapping更有用武之地,跟XMLBeans之流的对着干
有时候我倒是怀念起ETL
呵呵,兄弟,别这么较真么。
就和你用spring一样,虽然它大部分也是用xml配置,同样你也可以使用api方式和annotation,这个是每个开发者自己的选择。
xml只是目前的一种配置方式,后续是马上有计划实施api,annotation的配置。
哈哈,其实我是在使劲的想到底什么场景可运用
然后你提到了SOA,我就感慨了一下,无意跟你较真
大家都在分享对吧,这很宝贵——我是很希望你仔细给大家点场景提示
你描述的两个业务场景,基本上也就是我们现在遇到比较多的。只不过我们现在大范围进行重构,构建SOA服务时,第2个场景的问题就特别明显
OK,扯上了SOA,那就应该考虑叫做xmlbeanMapping更有用武之地,跟XMLBeans之流的对着干
有时候我倒是怀念起ETL
呵呵,兄弟,别这么较真么。
就和你用spring一样,虽然它大部分也是用xml配置,同样你也可以使用api方式和annotation,这个是每个开发者自己的选择。
xml只是目前的一种配置方式,后续是马上有计划实施api,annotation的配置。
发表评论
-
yugong QuickStart
2016-03-05 01:52 0几点说明 a. 数据迁移的方案可参见设计文档,oracl ... -
阿里巴巴开源项目: 阿里巴巴去Oracle数据迁移同步工具
2016-03-05 18:29 6551背景 08年左右,阿里巴巴开始尝试MySQL的相关 ... -
愚公performance
2016-03-02 17:29 0性能测试 全量测试 场景1 (单主键, ... -
yugong AdminGuide
2016-03-02 16:40 0环境要求 操作系统 数据库 迁移方案 部署 ... -
Tddl_hint
2014-01-27 13:52 0背景 工作原理 Hint格式 direct模 ... -
tddl5分库规则
2014-01-26 14:41 0背景 工作原理 构建语法树 元数据 基于 ... -
tddl5优化器
2014-01-22 15:12 0背景 工作原理 构建语法树 元数据 抽象语 ... -
Canal BinlogChange(mariadb5/10)
2014-01-20 17:25 4633背景 先前开源了一个 ... -
asynload quickstart
2013-10-08 22:49 0几点说明: 1. asyncload是做为一个j ... -
映射规则配置
2013-09-26 11:25 0背景 因为alibaba的特殊业务,比如: 同 ... -
网友文档贡献
2013-09-18 15:50 01. Otter源代码解析系列 链接:http://e ... -
Manager配置介绍
2013-09-16 13:00 0通道配置说明 多种同步方式配置 a. 单向同步 ... -
canal&otter FAQ
2013-09-05 17:30 0常见问题 1. canal和 ... -
阿里巴巴开源项目:分布式数据库同步系统otter(解决中美异地机房)
2013-08-22 16:48 40479项目背景 阿里巴巴B2B公司,因为业务的特性 ... -
Otter AdminGuide
2013-08-19 11:06 0几点说明 otter系统自带了manager,所以简化了一 ... -
Otter高可用性
2013-08-17 23:41 0基本需求 网络不可靠,异地机房尤为明显. man ... -
Otter数据一致性
2013-08-17 23:39 0技术选型分析 需要处理一致性的业务场景: 多地修改 ( ... -
Otter扩展性
2013-08-17 22:20 0扩展性定义 按照实现不同,可分为两类: 数据处理自定 ... -
Otter双向回环控制
2013-08-17 21:37 0基本需求 支持mysql/oracle的异构数据库的双 ... -
Otter调度模型
2013-08-17 20:13 0背景 在介绍调度模型之前,首先了解一下otter系统要解 ...
相关推荐
这个方法接收三个参数:目标对象`obj`,要定义或修改的属性名`prop`,以及一个描述符对象`descriptor`。描述符对象包含了关于属性的各种配置信息,如`configurable`、`enumerable`、`value`、`writable`等。 - `...
在这个场景中,“swt table 自己造个轮子”指的是使用SWT(Standard Widget Toolkit)库来创建一个自定义的表格组件。SWT是Eclipse项目的一部分,它提供了一套原生的GUI组件,用于Java应用程序,提供了与操作系统更...
不过让我感到有点困惑的是,怎么样才叫做不要重复制造轮子?如何才能站在巨人的肩旁上?现在网络如此发达,资源如此丰富,开源社区也发展的很好。有很多源代码可以下载,使用。那是不是说当我们在写一个程序的时候就...
在这个“STL仿造轮子”的项目中,我们旨在通过模仿SGI-STL(斯坦福大学图形小组的STL实现)来深入理解和学习C++以及数据结构的基本原理。 首先,STL的核心组件包括容器、迭代器、算法和函数对象。容器是STL的基础,...
通过这个程序,你可以轻松地与讯飞星火API建立连接,并实现与模型的交互。无论是简单的问答还是复杂的问题,它都能准确理解并给出满意的答案。而且,它还具备联系上下文的能力,能够更好地理解问题的语境,从而提供...
在IT行业中,"重复造轮子,表单验证"是一个常见的议题,特别是在软件开发中。当我们谈论表单验证时,通常是指在用户提交数据到服务器之前,在客户端(通常是Web浏览器)进行的数据验证过程。这个过程确保了用户输入...
这篇文档是关于北师大版小学数学二年级上册《需要几个轮子》课程的教学反思。这节课的主要目标是引导学生理解和应用乘法,特别是3的乘法口诀。教学过程中,教师通过创设小动物郊游的情境,激发学生兴趣,让学生自然...
WAF 绕过-权限控制之代码混淆及行为造轮子#Safedog 代码层手写及脚本绕过变量覆盖,加密混淆,异或生成#BT Aliyun 代码层手写及脚本绕过编码解码
4. 帮玩具宝宝数轮子:设置问题情境,让孩子们思考不同类型的车辆应该有多少个轮子,并动手操作。通过集体验证,确保每个孩子都能正确数清轮子。 5. 创意延伸:鼓励孩子们发挥想象力,设计自己的“参赛车辆”,并...
标题中的“为写简单HTML5展示页的同志们造的轮子基于AngularJS1xgulpswiper”表明这是一个专为构建HTML5展示页面而设计的项目,它整合了AngularJS 1.x、gulp和swiper这三种技术。AngularJS 1.x是Google维护的一个...
wheels前端造轮子~~~demoTODO(包含但不局限于以下轮子)Tab 选项卡文件上传通知提示框(弹出层)日期选择器分页单选框/复选框(, )更多...ps:造轮子过程中会参考成熟的 UI 框架,如:, ,轮子尽量减少对 jquery 的依赖
在Java编程语言中,封装和继承是面向对象编程(OOP)的两个核心概念。封装是一种将数据和方法捆绑在一起的机制,使数据受到保护,防止未经授权的访问和修改。继承则是从已有的类创建新类的过程,允许新类继承父类的...
# 【Unity造轮子】实现一个类csgo的武器轮盘功能 # 作者信息 姓名:向宇 博客:[https://xiangyu.blog.csdn.net/](https://xiangyu.blog.csdn.net/) # 文章说明: ...
这个压缩包文件"需要几个轮子_《需要几个轮子》练习四.rar"显然包含了书中的一个练习部分,可能是为了帮助读者加深对书本内容的理解和应用。主要的文件是一个名为"需要几个轮子_《需要几个轮子》练习四.pdf"的PDF...
在这个文件中,设计师会利用SolidWorks的各种工具来创建轮子的精确几何形状。设计过程可能包括绘制草图,定义参数,使用旋转、拉伸、倒角等特征来塑造轮子的轮廓。设计师还会考虑轮子的尺寸,如直径、宽度以及中心孔...
- **重点**:强调不同车子的轮子数量差异,例如独轮车有一个轮子,自行车有两个轮子,三轮车有三个轮子,而大部分汽车有四个轮子。 - **难点**:教授幼儿如何正确地将每辆车子与对应的轮子数量匹配,进行一一对应的...
在这个名为“完全自己造轮子的手势识别项目”的压缩包中,我们找到了一个关于人体关键点检测、人体属性分析、动作捕捉以及手势识别的研究或实践项目。这个项目旨在提供一个易于理解和使用的平台,促进相关领域的学习...