用jodd加载类并在drools中使用它们

时间:2012-07-03 21:10:06

标签: classloader drools jodd

我正在使用drools来评估某些对象的系统。但是,这些对象可以是使用jodd在运行时加载的类。我可以使用以下函数加载文件:

 public static void loadClassFile(File file) {
    try {
        // use Jodd ClassLoaderUtil to load class into the current ClassLoader
        ClassLoaderUtil.defineClass(getBytesFromFile(file));
    } catch (IOException e) {
        exceptionLog(LOG_ERROR, getInstance(), e);
    }
 }

现在假设我创建了一个名为Tire的类,并使用上面的函数加载它。有没有办法可以在我的规则文件中使用Tire类:

rule "Tire Operational"
when
    $t: Tire(pressure == 30)
then

end

现在,如果我尝试添加此规则,则会收到错误消息,指出无法解析ObjectType Tire。我的假设是我会在某种程度上需要在规则中导入Tire,但我不确定如何做到这一点。

1 个答案:

答案 0 :(得分:1)

自版本3以来没有使用Drools,但无论如何都会尝试提供帮助。当您以这种方式加载类时(动态地,在运行时,无论您是否使用例如Class.forName()或Jodd),加载的类名都无法在代码中显式使用。我相信我们可以使用以下sudo-code来简化您的问题,首先加载一个类,然后尝试使用它的名称:

defineClass('Tire.class');
Tire tire = new Tire();

这显然不起作用,因为在编译时Tire类型不可用:编译器不知道在执行期间你要加载什么类型。

让Tire实现某些界面(例如VehiclePart)会起作用。那么你可以使用以下sudo-code:

Class tireClass = defineClass('Tire.class');
VehiclePart tire = tireClass.newInstance();
System.out.println(tire.getPartName()); // prints 'tire' for example

然后,您可以通过VehiclePart和getPartName()属性接口构建Drools规则。

<强>附录

只有当界面涵盖动态加载类的所有属性时才有意义。在大多数情况下,这不是一个有效的解决方案:动态加载的类根本不共享属性。所以,这是另一种方法。

可以通过“扩展”类加载器类路径来解决此问题,而不是使用显式类加载。请注意,这是 hack

在Jodd中,有一种方法: ClassLoaderUtil.addFileToClassPath(),它可以在运行时中添加文件或路径到类加载器。以下是适用于我的步骤:

1)将所有动态创建的类放入一些根文件夹中,并尊重其包。例如,假设我们要使用 jodd.samples.TestBean 类,它有两个属性: number (int)和 value (串)。然后,我们需要将此类放入 root / jodd / samples 文件夹中。

2)构建所有动态类之后,扩展类加载器路径:

ClassLoaderUtil.addFileToClassPath("root", ClassLoader.getSystemClassLoader());

3)加载类并在创建KnowledgeBuilder之前创建它:

Class testBeanClass = Class.forName("jodd.samples.TestBean");
Object testBean = testBeanClass.newInstance();

4)此时你可以使用BeanUtils(来自Jodd,例如:)来操作testBean实例的属性

5)创建Drools内容并将insert testBean添加到session:

knowledgeSession.insert(testBean);

6)在规则文件中使用它:

import jodd.samples.TestBean;

rule "xxx"
    when
    $t: TestBean(number == 173)
then
    System.out.println("!!!");
end

这对我有用。请注意,在步骤#2中,您可以尝试使用不同的类加载器,但您可能需要它通过KnowledgeBuilderConfiguration(即PackageBuilderConfiguration)将其传递给KnowledgeBuilderFactory。

另一种解决方案

另一种解决方案是简单地将所有对象属性复制到地图,并处理规则文件中的地图。所以你可以在第4步使用这样的东西:

Map map = new HashMap();
BeanTool.copy(testBean, map);

以后(步骤#5)将地图添加到Drools上下文而不是bean实例。在这种情况下,使用 defineClass()方法明确定义每个类会更好。