La API JDBC es un excelente ejemplo de esto. De esta manera se puede configurar el controlador JDBC en el exterior, por ejemplo, un archivo de propiedades:
driver = com.dbvendor.jdbc.Driver
url = jdbc:dbvendor://localhost/dbname
username = stackoverflow
password = youneverguess
..which se puede utilizar como:
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);
Cada controlador JDBC aplicación básicamente registra a sí mismo en el interior de un DriverManager
static
bloque inicializador. Es el que se ejecuta durante 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");
}
}
Desde el DriverManager
más o menos el siguiente aspecto (que en realidad utiliza la antigua usanza Vector
)
private static final Set<Driver> drivers = new HashSet<Driver>();
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");
}
... se puede conseguir una conexión de ella sin la necesidad de crear una instancia del propio controlador !
De esta forma, el código JDBC es altamente portátil. Puede cambiar el DB o distribuir el código entre usuarios con diferentes DB sin la necesidad de cambiar/piratear/reconstruir el código en sí.
No es solo JDBC el que utiliza este enfoque, también otras API como Servlet API, ORM como Hibernate/JPA, marcos de inyección de dependencia, etcétera usa la reflexión para cargar las clases en archivos configurables externamente, archivos de configuración XML y/o anotaciones Todo hace que el código sea mucho más portátil y conectable.
Hibernate y AspectJ son ejemplos de creación de clases sobre la marcha. –