C3P0 DriverManagerDataSource initialization: http://donald-draper.iteye.com/blog/2343564
WrapperConnectionPoolDataSource initialization: http://donald-draper.iteye .com/blog/2345008
C3P0 property setting and database connection pool acquisition: http://donald-draper.iteye.com/blog/2345084
In the previous articles, we talked about ComboPooledDataSource and initialization of DriverManagerDataSource, today let's take a look at database connection Pool WrapperConnectionPoolDataSource; in the constructor that initializes AbstractComboPooledDataSource, there are so many sentences. The last article talked about DriverManagerDataSource. In this article, let's take a look at WrapperConnectionPoolDataSource
//AbstractComboPooledDataSource public AbstractComboPooledDataSource(boolean autoregister) { // super(autoregister); //Create a new driver data source manager dmds = new DriverManagerDataSource(); //Create a new database connection pool wcpds = new WrapperConnectionPoolDataSource(); //Set the data source driver manager of the data connection pool wcpds.setNestedDataSource(dmds); try { setConnectionPoolDataSource(wcpds); } catch(PropertyVetoException e) { logger.log(MLevel.WARNING, "Hunh??? This can't happen. We haven't set up any listeners to veto the property change yet!", e); throw new RuntimeException((new StringBuilder()).append("Hunh??? This can't happen. We haven't set up any listeners to veto the property change yet! ").append(e).toString()); } setUpPropertyEvents (); }
//Create a new database connection pool
wcpds = new WrapperConnectionPoolDataSource();
//WrapperConnectionPoolDataSource
public final class WrapperConnectionPoolDataSource extends WrapperConnectionPoolDataSourceBase implements ConnectionPoolDataSource { ConnectionTester connectionTester; Map userOverrides; public WrapperConnectionPoolDataSource() { this(true); } public WrapperConnectionPoolDataSource(boolean autoregister) { //Initialize WrapperConnectionPoolDataSourceBase super(autoregister); //Get the database connection test class, com.mchange.v2.c3p0.impl.DefaultConnectionTester connectionTester = C3P0Registry.getDefaultConnectionTester(); setUpPropertyListeners (); try { userOverrides = C3P0ImplUtils.parseUserOverridesAsString(getUserOverridesAsString()); } } //Set the property value change listener private void setUpPropertyListeners () { VetoableChangeListener setConnectionTesterListener = new VetoableChangeListener() { public void vetoableChange(PropertyChangeEvent evt) throws PropertyVetoException { String propName = evt.getPropertyName(); Object val = evt.getNewValue(); if("connectionTesterClassName".equals(propName)) try { //Recreate the connection test class recreateConnectionTester((String)val); } else if("userOverridesAsString".equals(propName)) try { userOverrides = C3P0ImplUtils.parseUserOverridesAsString((String)val); } } final WrapperConnectionPoolDataSource this$0; { this.this$0 = WrapperConnectionPoolDataSource.this; super(); } }; addVetoableChangeListener(setConnectionTesterListener); }
Let's look
at //WrapperConnectionPoolDataSourceBase
public abstract class WrapperConnectionPoolDataSourceBase extends IdentityTokenResolvable implements Referenceable, Serializable { protected PropertyChangeSupport pcs;//Auxiliary tool for property value change protected VetoableChangeSupport vcs;//Bean property change auxiliary tool private int acquireIncrement;// private int acquireRetryAttempts;//Get the number of connection attempts private int acquireRetryDelay; private boolean autoCommitOnClose;//Whether to commit automatically private String automaticTestTable; private boolean breakAfterAcquireFailure;//Whether it is disconnected when the connection fails to be acquired private int checkoutTimeout; private String connectionCustomizerClassName; private String connectionTesterClassName; private String contextClassLoaderSource; private boolean debugUnreturnedConnectionStackTraces; private String factoryClassLocation; private boolean forceIgnoreUnresolvedTransactions; private boolean forceSynchronousCheckins; private volatile String identityToken;//class唯一token private int idleConnectionTestPeriod; private int initialPoolSize;//Initialize connection pool size private int maxAdministrativeTaskTime; private int maxConnectionAge; private int maxIdleTime;//Maximum idle time private int maxIdleTimeExcessConnections; private int maxPoolSize;//The maximum number of connections in the connection pool private int maxStatements; private int maxStatementsPerConnection; private int minPoolSize;//The minimum number of connections in the connection pool private DataSource nestedDataSource;//Data source private String overrideDefaultPassword; private String overrideDefaultUser; private String preferredTestQuery; private boolean privilegeSpawnedThreads; private int propertyCycle; private int statementCacheNumDeferredCloseThreads; private boolean testConnectionOnCheckin; private boolean testConnectionOnCheckout; private int unreturnedConnectionTimeout; private String userOverridesAsString; private boolean usesTraditionalReflectiveProxies; private static final long serialVersionUID = 1L; private static final short VERSION = 1; static final JavaBeanReferenceMaker referenceMaker; static { referenceMaker = new JavaBeanReferenceMaker(); referenceMaker.setFactoryClassName("com.mchange.v2.c3p0.impl.C3P0JavaBeanObjectFactory"); referenceMaker.addReferenceProperty("acquireIncrement"); referenceMaker.addReferenceProperty("acquireRetryAttempts"); referenceMaker.addReferenceProperty("acquireRetryDelay"); referenceMaker.addReferenceProperty("autoCommitOnClose"); referenceMaker.addReferenceProperty("automaticTestTable"); referenceMaker.addReferenceProperty("breakAfterAcquireFailure"); referenceMaker.addReferenceProperty("checkoutTimeout"); referenceMaker.addReferenceProperty("connectionCustomizerClassName"); referenceMaker.addReferenceProperty("connectionTesterClassName"); referenceMaker.addReferenceProperty("contextClassLoaderSource"); referenceMaker.addReferenceProperty("debugUnreturnedConnectionStackTraces"); referenceMaker.addReferenceProperty("factoryClassLocation"); referenceMaker.addReferenceProperty("forceIgnoreUnresolvedTransactions"); referenceMaker.addReferenceProperty("forceSynchronousCheckins"); referenceMaker.addReferenceProperty("identityToken"); referenceMaker.addReferenceProperty("idleConnectionTestPeriod"); referenceMaker.addReferenceProperty("initialPoolSize"); referenceMaker.addReferenceProperty("maxAdministrativeTaskTime"); referenceMaker.addReferenceProperty("maxConnectionAge"); referenceMaker.addReferenceProperty("maxIdleTime"); referenceMaker.addReferenceProperty("maxIdleTimeExcessConnections"); referenceMaker.addReferenceProperty("maxPoolSize"); referenceMaker.addReferenceProperty("maxStatements"); referenceMaker.addReferenceProperty("maxStatementsPerConnection"); referenceMaker.addReferenceProperty("minPoolSize"); referenceMaker.addReferenceProperty("nestedDataSource"); referenceMaker.addReferenceProperty("overrideDefaultPassword"); referenceMaker.addReferenceProperty("overrideDefaultUser"); referenceMaker.addReferenceProperty("preferredTestQuery"); referenceMaker.addReferenceProperty("privilegeSpawnedThreads"); referenceMaker.addReferenceProperty("propertyCycle"); referenceMaker.addReferenceProperty("statementCacheNumDeferredCloseThreads"); referenceMaker.addReferenceProperty("testConnectionOnCheckin"); referenceMaker.addReferenceProperty("testConnectionOnCheckout"); referenceMaker.addReferenceProperty("unreturnedConnectionTimeout"); referenceMaker.addReferenceProperty("userOverridesAsString"); referenceMaker.addReferenceProperty("usesTraditionalReflectiveProxies"); } protected abstract PooledConnection getPooledConnection(ConnectionCustomizer connectioncustomizer, String s) throws SQLException; //Get the database connection pool, to be extended by the parent class of AbstractComboPooledDataSource protected abstract PooledConnection getPooledConnection(String s, String s1, ConnectionCustomizer connectioncustomizer, String s2) throws SQLException; //Initialize the database connection pool, the number of connections, the number of statment, the number of failed connections and other attributes public WrapperConnectionPoolDataSourceBase(boolean autoregister) { pcs = new PropertyChangeSupport(this); vcs = new VetoableChangeSupport(this); acquireIncrement = C3P0Config.initializeIntPropertyVar("acquireIncrement", C3P0Defaults.acquireIncrement()); acquireRetryAttempts = C3P0Config.initializeIntPropertyVar("acquireRetryAttempts", C3P0Defaults.acquireRetryAttempts()); acquireRetryDelay = C3P0Config.initializeIntPropertyVar("acquireRetryDelay", C3P0Defaults.acquireRetryDelay()); autoCommitOnClose = C3P0Config.initializeBooleanPropertyVar("autoCommitOnClose", C3P0Defaults.autoCommitOnClose()); automaticTestTable = C3P0Config.initializeStringPropertyVar("automaticTestTable", C3P0Defaults.automaticTestTable()); breakAfterAcquireFailure = C3P0Config.initializeBooleanPropertyVar("breakAfterAcquireFailure", C3P0Defaults.breakAfterAcquireFailure()); checkoutTimeout = C3P0Config.initializeIntPropertyVar("checkoutTimeout", C3P0Defaults.checkoutTimeout()); connectionCustomizerClassName = C3P0Config.initializeStringPropertyVar("connectionCustomizerClassName", C3P0Defaults.connectionCustomizerClassName()); connectionTesterClassName = C3P0Config.initializeStringPropertyVar("connectionTesterClassName", C3P0Defaults.connectionTesterClassName()); contextClassLoaderSource = C3P0Config.initializeStringPropertyVar("contextClassLoaderSource", C3P0Defaults.contextClassLoaderSource()); debugUnreturnedConnectionStackTraces = C3P0Config.initializeBooleanPropertyVar("debugUnreturnedConnectionStackTraces", C3P0Defaults.debugUnreturnedConnectionStackTraces()); factoryClassLocation = C3P0Config.initializeStringPropertyVar("factoryClassLocation", C3P0Defaults.factoryClassLocation()); forceIgnoreUnresolvedTransactions = C3P0Config.initializeBooleanPropertyVar("forceIgnoreUnresolvedTransactions", C3P0Defaults.forceIgnoreUnresolvedTransactions()); forceSynchronousCheckins = C3P0Config.initializeBooleanPropertyVar("forceSynchronousCheckins", C3P0Defaults.forceSynchronousCheckins()); idleConnectionTestPeriod = C3P0Config.initializeIntPropertyVar("idleConnectionTestPeriod", C3P0Defaults.idleConnectionTestPeriod()); initialPoolSize = C3P0Config.initializeIntPropertyVar("initialPoolSize", C3P0Defaults.initialPoolSize()); maxAdministrativeTaskTime = C3P0Config.initializeIntPropertyVar("maxAdministrativeTaskTime", C3P0Defaults.maxAdministrativeTaskTime()); maxConnectionAge = C3P0Config.initializeIntPropertyVar("maxConnectionAge", C3P0Defaults.maxConnectionAge()); //Initialize the maximum idle time maxIdleTime = C3P0Config.initializeIntPropertyVar("maxIdleTime", C3P0Defaults.maxIdleTime()); maxIdleTimeExcessConnections = C3P0Config.initializeIntPropertyVar("maxIdleTimeExcessConnections", C3P0Defaults.maxIdleTimeExcessConnections()); //Initialize the maximum number of connection pools maxPoolSize = C3P0Config.initializeIntPropertyVar("maxPoolSize", C3P0Defaults.maxPoolSize()); // maximum statements maxStatements = C3P0Config.initializeIntPropertyVar ("maxStatements", C3P0Defaults.maxStatements ()); maxStatementsPerConnection = C3P0Config.initializeIntPropertyVar ("maxStatementsPerConnection", C3P0Defaults.maxStatementsPerConnection ()); minPoolSize = C3P0Config.initializeIntPropertyVar("minPoolSize", C3P0Defaults.minPoolSize()); overrideDefaultPassword = C3P0Config.initializeStringPropertyVar("overrideDefaultPassword", C3P0Defaults.overrideDefaultPassword()); overrideDefaultUser = C3P0Config.initializeStringPropertyVar("overrideDefaultUser", C3P0Defaults.overrideDefaultUser()); preferredTestQuery = C3P0Config.initializeStringPropertyVar("preferredTestQuery", C3P0Defaults.preferredTestQuery()); privilegeSpawnedThreads = C3P0Config.initializeBooleanPropertyVar("privilegeSpawnedThreads", C3P0Defaults.privilegeSpawnedThreads()); propertyCycle = C3P0Config.initializeIntPropertyVar("propertyCycle", C3P0Defaults.propertyCycle()); statementCacheNumDeferredCloseThreads = C3P0Config.initializeIntPropertyVar("statementCacheNumDeferredCloseThreads", C3P0Defaults.statementCacheNumDeferredCloseThreads()); testConnectionOnCheckin = C3P0Config.initializeBooleanPropertyVar("testConnectionOnCheckin", C3P0Defaults.testConnectionOnCheckin()); testConnectionOnCheckout = C3P0Config.initializeBooleanPropertyVar("testConnectionOnCheckout", C3P0Defaults.testConnectionOnCheckout()); unreturnedConnectionTimeout = C3P0Config.initializeIntPropertyVar("unreturnedConnectionTimeout", C3P0Defaults.unreturnedConnectionTimeout()); userOverridesAsString = C3P0Config.initializeUserOverridesAsString(); usesTraditionalReflectiveProxies = C3P0Config.initializeBooleanPropertyVar("usesTraditionalReflectiveProxies", C3P0Defaults.usesTraditionalReflectiveProxies()); if(autoregister) { //get unique token identityToken = C3P0ImplUtils.allocateIdentityToken(this); //Register to the token Map of C3P0Registry. C3P0Registry.reregister(this); } } //Add bean property change listener public void addVetoableChangeListener(VetoableChangeListener vcl) { vcs.addVetoableChangeListener(vcl); } public synchronized DataSource getNestedDataSource() { return nestedDataSource; } //Set the data source, this is in the AbstractComboPooledDataSource constructor //Create a new driver data source manager //dmds = new DriverManagerDataSource(); //Create a new database connection pool //wcpds = new WrapperConnectionPoolDataSource(); //Set the data source driver manager of the data connection pool //wcpds.setNestedDataSource(dmds); public synchronized void setNestedDataSource(DataSource nestedDataSource) { DataSource oldVal = this.nestedDataSource; this.nestedDataSource = nestedDataSource; if(!eqOrBothNull(oldVal, nestedDataSource)) pcs.firePropertyChange("nestedDataSource", oldVal, nestedDataSource); } }
It can be seen from the above that the initialization of AbstractComboPooledDataSource mainly initializes the properties related to the database connection pool, such as the maximum and minimum number of database connections, idle time, the number of connection failure attempts, whether the transaction is automatically committed, and
statement-related properties.
//VetoableChangeListener
package java.beans; /** * A VetoableChange event gets fired whenever a bean changes a "constrained" * property. You can register a VetoableChangeListener with a source bean * so as to be notified of any constrained property updates. */ public interface VetoableChangeListener extends java.util.EventListener { /** * This method gets called when a constrained property is changed. * * @param evt a <code>PropertyChangeEvent</code> object describing the * event source and the property that has changed. * @exception PropertyVetoException if the recipient wishes the property * change to be rolled back. */ void vetoableChange(PropertyChangeEvent evt) throws PropertyVetoException; }
//VetoableChangeSupport
/** * This is a utility class that can be used by beans that support constrained * properties. It manages a list of listeners and dispatches * {@link PropertyChangeEvent}s to them. You can use an instance of this class * as a member field of your bean and delegate these types of work to it. * The {@link VetoableChangeListener} can be registered for all properties * or for a property specified by name. * <p> * Here is an example of {@code VetoableChangeSupport} usage that follows * the rules and recommendations laid out in the JavaBeans™ specification: * <pre> * public class MyBean { * private final VetoableChangeSupport vcs = new VetoableChangeSupport(this); * * public void addVetoableChangeListener(VetoableChangeListener listener) { * this.vcs.addVetoableChangeListener(listener); * } * * public void removeVetoableChangeListener(VetoableChangeListener listener) { * this.vcs.removeVetoableChangeListener(listener); * } * * private String value; * * public String getValue() { * return this.value; * } * * public void setValue(String newValue) throws PropertyVetoException { * String oldValue = this.value; * this.vcs.fireVetoableChange("value", oldValue, newValue); * this.value = newValue; * } * * [...] * } * </pre> * <p> * A {@code VetoableChangeSupport} instance is thread-safe. * <p> * This class is serializable. When it is serialized it will save * (and restore) any listeners that are themselves serializable. Any * non-serializable listeners will be skipped during serialization. * * @see PropertyChangeSupport */ public class VetoableChangeSupport implements Serializable { private VetoableChangeListenerMap map = new VetoableChangeListenerMap(); /** * Constructs a <code>VetoableChangeSupport</code> object. * * @param sourceBean The bean to be given as the source for any events. */ public VetoableChangeSupport(Object sourceBean) { if (sourceBean == null) { throw new NullPointerException(); } source = sourceBean; } /** * Add a VetoableChangeListener to the listener list. * The listener is registered for all properties. * The same listener object may be added more than once, and will be called * as many times as it is added. * If <code>listener</code> is null, no exception is thrown and no action * is taken. * * @param listener The VetoableChangeListener to be added */ public void addVetoableChangeListener(VetoableChangeListener listener) { if (listener == null) { return; } if (listener instanceof VetoableChangeListenerProxy) { VetoableChangeListenerProxy proxy = (VetoableChangeListenerProxy)listener; // Call two argument add method. addVetoableChangeListener(proxy.getPropertyName(), proxy.getListener()); } else { this.map.add(null, listener); } } }