Class.forName
JDBC 드라이버를 로드하는 코드를 보면 Class.forName을 사용하는 것을 볼 수 있다. 이 Class.forName의 의미는 무엇일까?
Class.forName("com.mysql.jdbc.Driver");
Connection conn = DriverManager.getConnection();
코드를 살펴보면 리턴값을 받지도 않고 DriverManager
의 getConnection
메서드를 바로 사용할 수 있다. 또 forName
의 인자로 패키지의 경로가 설정된 것을 볼 수 있다. 왜 이렇게 구현한 것일까?
각 JDBC마다 드라이버와 Connection의 구현은 다를 것이다. 각 DBMS마다 다른 API를 사용하여 DB에 연결할 경우 DBMS를 변경할 일이 생기면 복잡한 작업이 될 것이다. Java에서는 Connection, Driver 인터페이스와 Driver를 등록하고 그 드라이버의 Connection을 리턴해주는 DriverManager 클래스를 제공한다. 각 벤더에서는 Driver와 Conneciton을 구현하고 DriverManager라는 클래스를 통해 사용자가 이들을 사용 하도록한다.
xpackage serviceprovider;
public interface Connection {
}
// package serviceprovider;
public interface Driver {
Connection getConnection();
}
java는 위와 같은 두개의 인터페이스를 제공한다. 각 벤더는 이 인터페이스를 상속하여 드라이버와 커넥션을 구현한다.
xxxxxxxxxx
//DriverManager 예시
package serviceprovider;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
public class DriverManager {
private DriverManager() {}
private static final Map<String,Driver> drivers = new ConcurrentHashMap<String,Driver>();
public static final String DEFAULT_DRIVER_NAME = "default";
public static void registerDefaultPrivider(Driver d) {
System.out.println("Driver 등록");
registerDriver(DEFAULT_DRIVER_NAME, d);
}
public static void registerDriver(String name, Driver d) {
drivers.put(name,d);
}
public static Connection getConnection() {
return getConnection(DEFAULT_DRIVER_NAME);
}
public static Connection getConnection(String name) {
Driver d = drivers.get(name);
if(d==null) throw new IllegalArgumentException();
return d.getConnection();
}
}
DriverManger
는 드라이버를 등록하고 관리하는 기능을 제공한다. 우리가 처음에 DriverManager.getConnection
을 호출하면 여기에 저장이 된다. static으로 변수와 메소드가 선언되어 있기 때문에 객체 생성없이 바로 사용할 수 있다.
xxxxxxxxxx
//OracleDriver 클래스의 일부분
static {
defaultDriver = null; Timestamp timestamp = Timestamp.valueOf("2000-01-01 00:00:00.0");
try {
if(defaultDriver == null) {
defaultDriver = new OracleDriver();
DriverManager.registerDriver(defaultDriver);
}
} catch(RuntimeException runtimeexception) {
} catch(SQLException sqlexception) {
}
}
Class.forName(String name) 클래스에 의해 클래스가 로드 될 때 static 필드의 내용이 실행된다. <- 그렇다고 합니다. 이를 이용해 class 내부에 static 필드를 통해 자기 자신을 DriverManager 클래스에 등록한다. Java에서는 어떤 DB든 동일하게 사용할 수 있게 Connection과 DriverManger 등을 인터페이스로 제공하여 각 벤더가 이를 구현하게 만들었다. 이렇게 동일한 인터페이스로 구현하여 Class.forName을 통해 동적으로 객체를 가져와 사용할 수 있다. 결국 어떤 DBMS를 사용하든 DB 사용의 구현은 동일하게 할 수 있다.