2010-11-17 14 views
35

Ho appena saputo di java.sql package. Utilizza Class.forName() per caricare dinamicamente il driver che estende DriverManager. Quindi otteniamo la connessione usando il metodo DriverManager.getConnection().Come funziona Class.forName()?

Quindi come funziona tutto?
In che modo la classe DriverManager sa come ottenere la connessione senza utilizzare il nome classe del driver effettivo.

Inoltre possiamo usare Class.forName() per applicazioni personalizzate ... se questo è spiegato con un esempio, sarò molto felice.

+0

vedere anche http://stackoverflow.com/a/8053125/632951 – Pacerier

risposta

51

Class.forName carichi semplicemente una classe, tra cui l'esecuzione dei suoi inizializzatori statici, come questo:

class Foo { 
    static { 
     System.out.println("Foo initializing"); 
    } 
} 

public class Test { 
    public static void main(String [] args) throws Exception { 
     Class.forName("Foo"); 
    } 
} 

Tutto il resto della procedura di cui parli è JDBC-specifica. Il driver - che implementa Driver, non estende DriverManager - registra semplicemente un'istanza appropriata utilizzando DriverManager.registerDriver. Quindi, quando DriverManager deve trovare un driver per una particolare stringa di connessione, chiama a turno acceptsURL su ciascun driver registrato finché uno dice "Sì, posso essere il driver per quella connessione".

Si noti che questo modo di registrare i driver è ragionevolmente vecchio stile - guarda i documenti per DriverManager per i modi più moderni di ottenere a un'origine dati.

+0

la mia domanda è risolvere dal 1 ° linea per rispondete signore. – Simmant

+2

@Jon Bel esempio, ma dov'è la classe 'com.mysql.jdbc.Driver' per' Class.forName ("com.mysql.jdbc.Driver"); 'come ho provato a' importare com.mysql.jdbc.Driver 'ancora non funziona – UnKnown

+2

@UnNonosciuto: è nel file jar MySQL. Ma non dovresti aver bisogno di importarlo - di solito lascia che JDBC inizializzi direttamente, e fai riferimento solo alle classi JDBC nel tuo codice. –

12

Class.forName(..) carica e inizializza la classe di destinazione. . Ciò a sua volta significa che i blocchi di inizializzazione statici vengono richiamati (codice definito nel static { .. }

Se si guarda, ad esempio, il driver di MySQL, in quel blocco statico il conducente sta registrando in sé: DriverManager.registerDriver(new Driver());

è possibile omettere il Class.forName(..) e registrare il driver da soli se si può "permettersi" la dipendenza di compilazione on pilota di MySQL.

detto questo, sarà raramente essere rilevante per usare Class.forName(..) per inizializzare le classi dalla vostra applicazione, in quanto in fase di compilazione dipendenza è non è un problema lì.

Si noti inoltre che Class.forName(..)is no longer required per JDBC dalla versione 4. Utilizzando il meccanismo service provider è possibile istruire il gestore di driver su cosa caricare da una proprietà di sistema.

3

Il motivo per cui Class.forName() è spesso citato negli esempi SQL, è perché non c'era nessuna magia per dire al JDBC DriverManager come per mappare l'URL JDBC fornito ad un driver vero e proprio.

E.g. "mysql" dovrebbe mappare a una data classe MySQL, mappe "sottili" alla classe Oracle, "as400" esegue il mapping alla classe DB2/400.

Caricando esplicitamente la classe, questo ha permesso di eseguire il codice all'interno della classe registrandosi con il DriverManager.

In questi giorni sono presenti i ganci magici che consentono alla JVM di individuare automaticamente i driver (se nuovi), quindi la chiamata è superflua, ma per abitudine molti lo usano ancora.

4

Quando creiamo un instace di una classe utilizzando nuovo operatore, fa due cose

  1. caricare la classe di memoria, se non viene caricato - che significa creare rappresentazione in memoria della classe dal file .class in modo che un'istanza possa essere creata al di fuori di esso. Ciò include l'inizializzazione delle variabili statiche (risoluzione di quella classe)
  2. creare un'istanza di tale classe e memorizzare il riferimento alla variabile.

Class.forName fa solo la prima cosa. Carica la classe in memoria e restituisce tale riferimento come un'istanza di Class. Se vogliamo creare un'istanza, possiamo chiamare il metodo newInstance di quella classe. che invocherà il costruttore predefinito (nessun costruttore di argomenti). Si noti che se il costruttore predefinito non è accessibile, il metodo newInstance genererà un IllegalAccessException. e se la classe è una classe astratta o un'interfaccia o non ha un costruttore predefinito, allora genererà uno InstantiationException. Se si verifica un'eventuale eccezione durante la risoluzione di tale classe, verrà generato un valore ExceptionInInitializerError.

Se il costruttore predefinito non è definito, è necessario richiamare il costruttore del defiend utilizzando l'API di reflection.

Ma il vantaggio principale con Class.forName è che può accettare il nome della classe come argomento String. Quindi possiamo passare il nome della classe in modo dinamico. Ma se creiamo un'istanza di una classe utilizzando un nuovo operatore, il nome della classe non può essere modificato dinamicamente.

Class.forName() inturn chiamerà il metodo loadClass del chiamante ClassLoader (ClassLoder della classe da cui viene richiamato Class.forName).

Per impostazione predefinita, lo Class.forName() risolve quella classe. il che significa inizializzare tutte le variabili statiche all'interno di quella classe. stesso può essere modificato utilizzando il metodo sovraccarico di Class.forName(String name,boolean initialize,ClassLoader loader)

Il motivo principale per il caricamento del driver jdbc utilizzando Class.forName() è, il driver può cambiare in modo dinamico. nel blocco statico tutti i driver creeranno un'istanza di se stessi e registreranno tale classe con DriverManager utilizzando il metodo DriverManager.registerDriver(). Poiché lo standard Class.forName(String className) risolve la classe, inizializzerà l'inizializzatore statico. Così, quando chiamiamo Class.forName("com.sun.jdbc.odbc.JdbcOdbcDriver"), la classe driver viene caricato, istanziare e registra con DriverManager

Quindi, se si utilizza nuovo operatore che devi fare le seguenti cose.
Codice:

Driver drv = new com.sun.jdbc.odbc.JdbcOdbcDriver(); 
DriverManager.registerDriver(drv);