15. Enhancement增强
As we have seen both Transparent Activation and Native Queries will produce correct results out-of-the-box.
正如我们所见,db4o的透明激活和原生查询都能得到可以拿来即用的正确结果。
To get your application to run as fast as possible with db4o, you will want to make sure that only required objects are loaded from the database and that Native Queries are optimized to use field indexes where this is possible.
为了让你的程序在db4o下跑得越快越好, 你希望确认对象是被按需从数据库中加载的、原生查询通过使用字节索引进行了优化。
Theoretically you could write all the necessary code by hand but you will save yourself a lot of time if you use automatic enhancement.
理论上你可以手工写所须的代码,但是如果你使用自动化增强,那将会节省出不少时间来。
The db4o enhancer tools will add code to your persistent classes to make them work even better with db4o.
db4o增强器工具可以在你的持久化类里中添加代码,从而使它们能和db4o更好地工作在一起。
db4o for Java supplies three different enhancer strategies:
- Enhancing at Compile/Deployment Time
- Enhancing at Class Loading Time
- Native Query Optimization at Query Execution Time
db4o对Java提供了3个不同的增强策略:
- 编译/部署时增强
- 类加载时增强
- 在查询执行时的原生查询优化
15.1. Required Libraries所需类库
The enhancer tasks require the addition of the following libraries to your project:
要使用增强器任务的话,就需要增加下面这些额外的类库到你的项目中:
ant.jar
for using the Ant
enhancer task
用于Ant
增强器任务
bloat-1.0.jar
the bytecode optimization library
bytecode优化库
db4o-7.0-classedit.jar
the classfile editor
类文件编辑器
db4o-7.0-java5.jar
the db4o core engine
db4o核心引擎
db4o-7.0-nqopt.jar
the Native Query Optimizer
原生查询优化器
db4o-7.0-taj.jar
the Transparent Activation Framework for Java
用于Java的透明激活框架
db4o-7.0-tools.jar
the tools interface that provides the top level enhancer tasks.
提供上层增强器任务的工具接口
15.2. Enhancing at Compile Time编译时增强
The db4o enhancer adds code to class files or jar files. Afterwards these files will be slightly different to what the debugger expects.
db4o增强器向类文件或jar文件中增加了代码。在此之后,这些文件将稍微不同于调试器所期望的那样。
In the setup the db4o team has been working with, using the Eclipse IDE, enhancing has worked perfectly when files were instrumented in-place, directly in the /bin/ directory where the Eclipse compiler places compiled class files. In all our tests the Eclipse debugger simply ignored additional statements and stepped over them and debugging worked perfectly as usual.
在开发时遵守db4o团队一直使用的工作设置:使用Eclipse的集成开发环境、把类文件直接放到/bin/目录(Eclipse编译器存放编译好的class文件的目录),这样可以使增强功能运行很好。而在我们所有的测试里,调试器简单地忽略掉额外的语句,并直接跳过它们,这样调试像平常一样工作良好。
The db4o enhancer technology is new. Not all possible development environment setups have been checked by the db4o team and there may be incompatibility issues with your IDE when enhancing class and library files in place. By trying out in-place enhancement with your setup and by reporting back issues to the db4o forums
you can help the db4o team to improve enhancement for your personal setup. A possible strategy to resolve problems with in-place enhancement would be to use different output directories than /bin and /lib as output paths for the enhancer and to run your enhanced application from there.
db4o的增强器技术是新颖独特的。但db4o团队并没有测试所有可能的开发环境,因此当增强类和库文件同时存在时,它们可能会和你的集成开发环境存在有些不兼容的问题。通过在工作环境中大胆尝试增强功能,然后把结果反馈给db4o论坛
,你可以帮助db4o团队来改善你自己配置的增强功能。解决此类问题的方法是:使用与/bin、/lib不同的目录作为增强器使用的输出目录,然后从那里运行你的增强应用。
15.2.1. Enhancing with Ant使用Ant增强
db4otools.jar contains the main enhancer task:
db4otools.jar包含主要的增强任务:
com.db4o.enhance.Db4oEnhancerAntTask
For all possibilities of using this task see the topic on build time enhancement
in the reference documentation.
关于使用这个任务时的详细情况,请查看参考文档中关于构建时增强的相关话题
。
The simplest enhancer task does both: It optimizes Native Queries and it adds the Activatable interface to your classes, making sure a persistent object is activated whenever any field is read.
最简单的增强器任务:优化原生查询而且为类增加可激活接口,以确保无论何时读取任何字段,相应的持久化对象都会被激活。
Here is an example of how an Ant
script could look like. This script enhances all class files and jar files except for the db4o libraries in-place, in the /bin and /lib directory of your project:
这里是一个使用Ant
脚本的例子。此脚本增强了除db4o库之外的存放在/bin和/lib文件夹下的所有类文件和jar文件:
<?xml version="1.0"?>
<project name="db4o enhance project" default="enhance" basedir=".">
<path id="project.classpath">
<pathelement path="${basedir}/bin" />
<fileset dir="lib">
<include name="**/*.jar"/>
</fileset>
</path>
<taskdef name="db4o-enhance"
classname="com.db4o.enhance.Db4oEnhancerAntTask"
classpathref="project.classpath" />
<target name="enhance">
<db4o-enhance classtargetdir="${basedir}/bin" jartargetdir="${basedir}/lib">
<classpath refid="project.classpath" />
<sources dir="${basedir}/bin" />
<jars dir="${basedir}/lib">
<include name="*.jar" />
<exclude name="db4o-*.jar" />
<exclude name="ant.jar" />
<exclude name="bloat-1.0.jar" />
</jars>
</db4o-enhance>
</target>
</project>
If you use Eclipse, there is a very convenient way to make sure an Ant script is executed every time after compilation and before you run your application: You can add a builder to your project. To do this, right click on your project, choose "Properties" + "Builders" + "New" + "Ant Builder" and enter the name of the build file you created.
如果你使用Eclipse,这里有一个很方便的方法来确保在每次编译之后、运行之前执行一个Ant脚本:增加一个构建器(builder)到你的项目中。右键点击项目,选择"属性" + "构建器" + "新建" + "Ant构建器",然后输入所创建的文件名。
15.2.2. Programmatic Enhancement程序化增强
The db4o enhancer is just another Java application so of course you can start it directly. The enhancer user interface is a convenience interface to the underlying instrumentation layer. To take advantage of all the possibilities you may want to consider a look at the sources of com.db4o.instrumentation.main.Db4oFileInstrumentor and call instrumentation directly.
db4o增强器就是一个Java程序,因此你当然可以直接启动它。增强器的用户接口对于下面的设备层来讲是一个方便的接口。如果要充分利用所有可用功能的话,你可以要考虑查看一下com.db4o.instrumentation.main.Db4oFileInstrumentor的源代码,并且直接调用其中的instrumentation。
Here is a very basic example how you could enhance all the files in the /bin folder below the project 'myproject' using the Db4oFileEnhancer:
这里是一个很基础的例子,它示范了如何使用Db4oFileEnhancer来增强'myproject'项目下/bin文件夹里的所有文件:
import com.db4o.enhance.*;
public static void main(String[] args) throws Exception {
String path = "../myproject/bin";
new Db4oFileEnhancer().enhance(path, path);
}
15.3. Enhancing at Load Time加载时增强
As an alternative to enhancing classes at build time, it is also possible to run a db4o application using a special launcher. Under the hood the Db4oEnhancedLauncher installs a special ClassLoader that instruments classes for db4o on the fly, when they are loaded.
除了在构建时增强,还可以使用特殊的执行器(launcher)来运行db4o项目,从而达到增强类的目的。通过db4oEnhancedLauncher来安装一种特殊的类装载器(ClassLoader),后者将使db4o的低层类被飞速地装载。
For using the launcher, please see the method signatures of
为了使用此执行器,请看下面的方法:
Db4oEnhancedLauncher#launch()
15.4. NQ Optimization at Querying Time在查询时的原生查询优化
In case no other enhancer has been run previously, Native Queries will still be optimized automatically if the following optimization libraries are found in the CLASSPATH:
bloat-1.0.jar, db4o-7.0-classedit.jar, db4o-7.0-nqopt.jar
在没有运行过其它的增强器的情况下,只要在CLASSPATH里能找到下面的优化类库,原生查询便会被自动优化:
bloat-1.0.jar, db4o-7.0-classedit.jar, db4o-7.0-nqopt.jar
The Native Query optimizer is still under development to eventually "understand" all Java constructs. Current optimization supports the following constructs well:
- compile-time constants
- simple member access
- primitive comparisons
- #equals() on primitive wrappers and Strings
- #contains()/#startsWith()/#endsWith() for Strings
- arithmetic expressions
- boolean expressions
- static field access
- array access for static/predicate fields
- arbitrary method calls on static/predicate fields (without candidate based params)
- candidate methods composed of the above
- chained combinations of the above
原生查询优化器目前正在开发中,因此尚不能理解所有的Java结构。当前的优化器能够很好地支持以下的结构:
- 编译期常量
- 简单成员访问
- 原始(primitive)类型的比较
- 原始类型的封装类和String的equals方法
- String的contains()、startsWith()和endsWith()方法
- 数学表达式
- 布尔表达式
- 静态字段访问
- 静态或断言(predicate)字段的数组访问
- 静态或断言(predicate)字段的任意的方法调用(没有基于参数的候选方法)
- 以上所述情况的断言(predicate)方法
- 以上所述情况的链式组合
Note that the current implementation does not support polymorphism and multiline methods yet.
注意:当前的实现还不支持多态机制和多行(multiline)方法。
15.5. Monitoring Native Query optimization监视原生查询优化
To find out if a Native Query runs optimized or unoptimized you can attach a query execution listener as follows:
要验证一个原生查询在执行时是否被优化,你可以按照下面的方式添加一个查询执行的监听器:
((ObjectContainerBase)db).getNativeQueryHandler().addListener(new Db4oQueryExecutionListener() {
public void notifyQueryExecuted(NQOptimizationInfo info) {
System.err.println(info);
}
});
The listener will be notified on each native query call and will be passed the Predicate object processed, the optimized expression tree (if successful) and the success status of the optimization run:
在每次调用原生查询时,监听器都会被通知、并被传递给被处理的断言对象、被优化的表达式树(如果成功)和优化运行的成功状态:
NativeQueryHandler.UNOPTIMIZED ("UNOPTIMIZED")
if the predicate could not be optimized and is run in unoptimized mode
如果断言不能被优化,则运行在非优化模式下。
NativeQueryHandler.PREOPTIMIZED ("PREOPTIMIZED")
if the predicate already was optimized (due to class file or load time instrumentation)
如果断言已经被优化(由类文件或者装载时低层类决定)。
NativeQueryHandler.DYNOPTIMIZED ("DYNOPTIMIZED")
if the predicate was optimized at query execution time
如果断言在查询执行时被优化。