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 사용의 구현은 동일하게 할 수 있다.