简体   繁体   English

根据类路径在属性文件中加载Java类

[英]Load Java classes based on a classpath in a properties file

My application uses JDBC database drivers. 我的应用程序使用JDBC数据库驱动程序。 I load these from a jar file, db2jcc.jar in the case of DB2 which I'm currently working with. 对于当前正在使用的DB2,我从jar文件db2jcc.jar加载这些文件。 With this jar in the classpath, everything is fine, but I have a requirement to find the jar from a property in the application's config file instead - for example, 将这个jar放在类路径中,一切都很好,但是我需要从应用程序的配置文件中的属性中查找jar,例如,

database.driver=/opt/IBM/db2/V9.5/java/db2jcc.jar

I can load the class via a URLClassLoader ok, but the problem is that I need to treat the object thus created as an explicit DB2XADataSource. 我可以通过URLClassLoader加载类,但是问题是我需要将这样创建的对象视为显式DB2XADataSource。 For example: 例如:

URLClassLoader dbClassLoader = new URLClassLoader(new URL[]{driverJar});
xaClass = dbClassLoader.loadClass("com.ibm.db2.jcc.DB2XADataSource");

DB2XADataSource dataSource = (DB2XADataSource) xaClass.newInstance();

dataSource.setCurrentSchema(DATABASE_SCHEMA); // <- dataSource has to be a 
dataSource.setDatabaseName(DATABASE_NAME);    // DB2XADataSource to do this

(rearranged and renamed somewhat; I actually do the loadClass in the constructor of the class that contains this code, while the newInstance is in one of its methods.) (经过重新排列和重命名;实际上,我在包含此代码的类的构造函数中执行loadClass,而newInstance在其方法之一中。)

I guess I'm getting into a classloader tangle because the classloader that loaded my class is trying to find DB2XADataSource in order to do the cast, but the URL classloader is not above it in the tree. 我猜我正在陷入类加载器的纠结中,因为加载了我的类的类加载器正试图找到DB2XADataSource以便进行转换,但是URL类加载器不在树中。 The trouble is, it being long after I should have stopped working for the day (here in the UK) I can't think how best to solve it in a vaguely neat and sane manner. 问题是,我应该停止一天的工作(在英国这里)已经很长时间了,我想不出如何最好地解决这种模糊而整洁的理智方法。

Ideas? 有想法吗?

Thanks. 谢谢。

The simplest approach is to just use the java.beans API (or direct reflection if you must) to invoke the setter methods. 最简单的方法是仅使用java.beans API(或必须直接反射)来调用setter方法。

Alternatively: Your database code requires to link to the dynamically loaded code. 或者:您的数据库代码需要链接到动态加载的代码。 Therefore, dynamically load your database code. 因此,动态加载您的数据库代码。 How much is up to you. 多少由您决定。 You might load almost everything except the "bootstrap". 您可能会加载除“引导程序”之外的几乎所有内容。

Yep - the class can't load its own dependencies. 是的-该类无法加载自己的依赖项。 You could do some ClassLoader magic, but I imagine it would get messy very quickly. 您可以做一些ClassLoader魔术,但是我想它会很快变得混乱。

One way to reduce the amount of reflection would be to put any code that depends on DB2XADataSource into an implementation that is invoked via an interface available to the calling ClassLoader. 减少反射量的一种方法是将依赖DB2XADataSource的所有代码放入通过可通过调用ClassLoader可用的接口调用的实现中。

//in mydb2driver.jar
public class MyDb2Driver implements IDriver {

    private DB2XADataSource dataSource = new DB2XADataSource();

    public void init() {
        dataSource.setCurrentSchema(DATABASE_SCHEMA);
    }

    //etc.

}

This is loaded with your driver: 这随您的驱动程序一起加载:

database.driver=/opt/IBM/db2/V9.5/java/db2jcc.jar:/foo/mydb2driver.jar

Invoking code is in the regular classpath: 调用代码在常规类路径中:

public interface IDriver {
    public void init();
    //etc.
}

...

URLClassLoader dbClassLoader = new URLClassLoader(new URL[]{driverJar});
xaClass = dbClassLoader.loadClass("foo.MyDb2Driver");
IDriver dataSource = (IDriver) xaClass.newInstance();
dataSource.init();

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM