Как динамически загрузить драйвер JDBC во время выполнения, начиная с Java 9?

Попробуйте следующее:

TextField tf = new TextField();
TextField tf2 = new TextField();
pane.getChildren().add(tf);
pane.getChildren().add(tf2);

Причина, по которой вы не можете добавить один и тот же узел дважды, состоит в том, что в gui можно просматривать только один узел с теми же спецификациями и размерами. Это было бы похоже на копирование идентичного синего круга на оригинальный синий круг. Для пользователя он выглядит одинаково, но он занимает больше памяти.

0
задан M. Folte 16 January 2019 в 12:17
поделиться

1 ответ

Незнание класса водителя кажется странным ограничением.

Я бы выбрал специальный загрузчик классов, который после инициализации класса (я думаю, вы можете сделать это) вызывает DriverManager.getDrivers и регистрирует любые новые драйверы, которые он находит. (У меня нет времени на написание кода.)

Хакерской альтернативой было бы загрузить весь ваш код (кроме начальной загрузки) в URLClassLoader и addURL к этому.

Редактировать: Итак, я написал некоторый код.

Он создает загрузчик классов для драйверов, который также содержит класс «scout», который пересылает DriverManager.drivers (который является непослушным методом, чувствительным к вызывающим абонентам (новый!). Поддельный драйвер в загрузчике класса приложения перенаправляет попытки подключения к любым динамически загружаемым драйверам во время запроса.

У меня нет драйверов для JDBC 4.0 или более поздней версии, чтобы можно было это протестировать. Вы, вероятно, захотите изменить URL - вам понадобится класс Scout и банка с драйверами.

import java.lang.reflect.*;
import java.net.*;
import java.sql.*;
import java.util.*;
import java.util.logging.*;
import java.util.stream.*;

class FakeJDBCDriver {
    public static void main(String[] args) throws Exception {
        URLClassLoader loader = URLClassLoader.newInstance(
            new URL[] { new java.io.File("dynamic").toURI().toURL() },
            FakeJDBCDriver.class.getClassLoader()
        );
        Class<?> scout = loader.loadClass("Scout");
        Method driversMethod = scout.getMethod("drivers");
        DriverManager.registerDriver(new Driver() {
            public int getMajorVersion() {
                return 0;
            }
            public int getMinorVersion() {
                return 0;
            }
            public Logger getParentLogger() throws SQLFeatureNotSupportedException {
                throw new SQLFeatureNotSupportedException();
            }
            public DriverPropertyInfo[] getPropertyInfo(String url, Properties info) {
                return new DriverPropertyInfo[] { };
            }
            public boolean jdbcCompliant() {
                return false;
            }
            public boolean acceptsURL(String url) throws SQLException {
                if (url == null) {
                    throw new SQLException();
                }
                for (Iterator<Driver> iter=drivers(); iter.hasNext(); ) {
                    Driver driver = iter.next();
                    if (
                        driver.getClass().getClassLoader() == loader &&
                        driver.acceptsURL(url)
                    ) {
                        return true;
                    }
                }
                return false;
            }
            public Connection connect(String url, Properties info) throws SQLException {
                if (url == null) {
                    throw new SQLException();
                }
                for (Iterator<Driver> iter=drivers(); iter.hasNext(); ) {
                    Driver driver = iter.next();
                    if (
                        driver.getClass().getClassLoader() == loader &&
                        driver.acceptsURL(url)
                    ) {
                        Connection connection = driver.connect(url, info);
                        if (connection != null) {
                            return connection;
                        }
                    }
                }
                return null;
            }
            private Iterator<Driver> drivers() {
                try {
                    return ((Stream<Driver>)driversMethod.invoke(null)).iterator();
                } catch (IllegalAccessException exc) {
                    throw new Error(exc);
                } catch (InvocationTargetException exc) {
                    Throwable cause = exc.getTargetException();
                    if (cause instanceof Error) {
                        throw (Error)cause;
                    } else if (cause instanceof RuntimeException) {
                        throw (RuntimeException)cause;
                    } else {
                        throw new Error(exc);
                    }
                }
            }
        });

        // This the driver I'm trying to access, but isn't even in a jar.
        Class.forName("MyDriver", true, loader);

        // Just some nonsense to smoke test.
        System.err.println(DriverManager.drivers().collect(Collectors.toList()));
        System.err.println(DriverManager.getConnection("jdbc:mydriver"));
    }
}

Внутри каталога dynamic (относительно текущего рабочего каталога):

import java.sql.*;

public interface Scout {
    public static java.util.stream.Stream<Driver> drivers() {
        return DriverManager.drivers();
    }
}

Я бы всегда предлагал избегать установки загрузчика класса контекста потока на что-либо кроме загрузчика, который все отрицает, или, возможно, null.

Модули вполне могут позволить вам аккуратно загружать драйверы, но я не смотрел.

0
ответ дан Tom Hawtin - tackline 16 January 2019 в 12:17
поделиться
Другие вопросы по тегам:

Похожие вопросы: