Загрузка классов Java на основе пути к классам в файле свойств - PullRequest
0 голосов
/ 21 апреля 2009

Мое приложение использует драйверы базы данных JDBC. Я загружаю их из файла jar, db2jcc.jar для DB2, с которым я сейчас работаю. С этим jar-адресом в classpath все в порядке, но у меня есть требование найти вместо этого jar-файл из свойства в файле конфигурации приложения - например,

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

Я могу загрузить класс через URLClassLoader, но проблема в том, что мне нужно обработать объект, созданный таким образом, как явный DB2XADataSource. Например:

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

(несколько переставил и переименовал; на самом деле я делаю loadClass в конструкторе класса, который содержит этот код, в то время как newInstance находится в одном из его методов.)

Полагаю, я попал в клубок загрузчика классов, потому что загрузчик классов, который загрузил мой класс, пытается найти DB2XADataSource для выполнения приведения, но загрузчик классов URL не находится над ним в дереве. Проблема в том, что спустя много времени после того, как я должен был перестать работать на день (здесь, в Великобритании), я не могу придумать, как лучше это решить, смутно и аккуратно.

Идеи

Спасибо.

Ответы [ 2 ]

1 голос
/ 22 апреля 2009

Самый простой подход - просто использовать API java.beans (или прямое отражение, если необходимо) для вызова методов установки.

В качестве альтернативы: код вашей базы данных требует ссылки на динамически загружаемый код. Поэтому динамически загружайте код вашей базы данных. Как много зависит от вас. Вы можете загрузить почти все, кроме «начальной загрузки».

0 голосов
/ 22 апреля 2009

Да - класс не может загружать свои собственные зависимости. Вы могли бы сделать магию ClassLoader, но я думаю, что это очень быстро запутается.

Один из способов уменьшить количество отражений - поместить любой код, который зависит от DB2XADataSource , в реализацию, которая вызывается через интерфейс, доступный для вызывающего ClassLoader.

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

    private DB2XADataSource dataSource = new DB2XADataSource();

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

    //etc.

}

Это загружено с вашим драйвером:

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

Код вызова находится в обычном пути к классам:

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();
...