What do people use class loading for?

前端 未结 18 1786
暗喜
暗喜 2021-02-02 14:26

So, every Java text book talks about how flexible Java is since it can load classes at run time. Just cobble together a string and give it to Class.forName(), and

18条回答
  •  渐次进展
    2021-02-02 15:12

    The JDBC API is an excellent example for this. This way you can configure the JDBC driver externally in for example a properties file:

    driver = com.dbvendor.jdbc.Driver
    url = jdbc:dbvendor://localhost/dbname
    username = stackoverflow
    password = youneverguess
    

    ..which you can use as:

    Properties properties = new Properties();
    properties.load(Thread.currentThread().getResourceAsStream("jdbc.properties"));
    
    String driver = properties.getProperty("driver");
    String url = properties.getProperty("url");
    String username = properties.getProperty("username");
    String password = properties.getProperty("password");
    
    Class.forName(driver);
    Connection connection = DriverManager.getConnection(url, username, password);
    

    Every JDBC driver implementation basically registers itself in the DriverManager inside a static initializer block. It's namely the one which get executed during Class#forName().

    package com.dbvendor.jdbc;
    
    public class Driver implements java.sql.Driver {
    
        static {
             java.sql.DriverManager.registerDriver(new Driver());
        }
    
        private Driver() {
            // ...
        }
    
        public boolean acceptsURL(String url) {
            return url.startsWith("jdbc:dbvendor");
        }
    
    }
    

    Since the DriverManager roughly look like this (it actually uses the old fashioned Vector)

    private static final Set drivers = new HashSet();
    
    public static void registerDriver(Driver driver) {
        drivers.add(driver);
    }
    
    public static Connection getConnection(String url, String username, String password) throws SQLException {
        for (Driver driver : drivers) {
            if (driver.acceptsURL(url)) {
                return driver.connect(url, username, password);
            }
        }
        throw new SQLException("No suitable driver");
    }
    

    ...you can get a connection from it without the need to instantiate the driver itself!

    This way the JDBC code is highly portable. You can change the DB or distribute the code among users with different DB's without the need to change/hack/rebuild the code itself.

    It's not only JDBC which uses this approach, also other API's such as Servlet API, ORM's like Hibernate/JPA, dependency injection frameworks, etcetera uses reflection to load the classes based on externally configureable propertiesfiles, XML config files and/or annotations. It all just makes the code much more portable and pluggable.

提交回复
热议问题