- 浏览: 984129 次
文章分类
- 全部博客 (428)
- Hadoop (2)
- HBase (1)
- ELK (1)
- ActiveMQ (13)
- Kafka (5)
- Redis (14)
- Dubbo (1)
- Memcached (5)
- Netty (56)
- Mina (34)
- NIO (51)
- JUC (53)
- Spring (13)
- Mybatis (17)
- MySQL (21)
- JDBC (12)
- C3P0 (5)
- Tomcat (13)
- SLF4J-log4j (9)
- P6Spy (4)
- Quartz (12)
- Zabbix (7)
- JAVA (9)
- Linux (15)
- HTML (9)
- Lucene (0)
- JS (2)
- WebService (1)
- Maven (4)
- Oracle&MSSQL (14)
- iText (11)
- Development Tools (8)
- UTILS (4)
- LIFE (8)
最新评论
-
Donald_Draper:
Donald_Draper 写道刘落落cici 写道能给我发一 ...
DatagramChannelImpl 解析三(多播) -
Donald_Draper:
刘落落cici 写道能给我发一份这个类的源码吗Datagram ...
DatagramChannelImpl 解析三(多播) -
lyfyouyun:
请问楼主,执行消息发送的时候,报错:Transport sch ...
ActiveMQ连接工厂、连接详解 -
ezlhq:
关于 PollArrayWrapper 状态含义猜测:参考 S ...
WindowsSelectorImpl解析一(FdMap,PollArrayWrapper) -
flyfeifei66:
打算使用xmemcache作为memcache的客户端,由于x ...
Memcached分布式客户端(Xmemcached)
C3P0 ComboPooledDataSource初始化:http://donald-draper.iteye.com/blog/2343522
C3P0 DriverManagerDataSource初始化:http://donald-draper.iteye.com/blog/2343564
WrapperConnectionPoolDataSource初始化:http://donald-draper.iteye.com/blog/2345008
C3P0属性设置和数据库连接池的获取:http://donald-draper.iteye.com/blog/2345084
在我们开发的时候经常会用到数据源,我们从数据源获取连接,今天我们就通过C3P0以探究竟。
测试主类:
我们从这一句来看
从AbstractComboPooledDataSource初始化,我们可以看出,
初始化就是创建数据源驱动管理器DriverManagerDataSource,
创建数据库连接池WrapperConnectionPoolDataSource,初始化数据库连接池的数据源驱动管理器,然后,初始化AbstractComboPooledDataSource的WrapperConnectionPoolDataSource。
再来看AbstractPoolBackedDataSource的构造
从AbstractPoolBackedDataSource的构造可以看出主要是添加属性change监听器,当AbstractPoolBackedDataSource的
属性值有变化时,重置连接池管理器。
//C3P0PooledConnectionPoolManager
再来看PoolBackedDataSourceBase的构造:
从上面可以看出,PoolBackedDataSourceBase的构造函数中,主要初始化属性辅助工具,初始化数据源name
//C3P0配置项
来看C3P0Config的findLibraryC3P0Config函数
//C3P0Config,初始化C3P0Config
来看一下DefaultC3P0ConfigFinder如何获取配置C3P0Config
//发现配置文件
protoMain = cfgFinder.findConfig();
//DefaultC3P0ConfigFinder
来看这一句
//如果xml文件不存在,则从C3P0Defaults获取默认属性
out = C3P0ConfigUtils.configFromFlatDefaults(flatDefaults);
//C3P0ConfigUtils
根据C3P0Defaults默认属性,配置C3P0Config
至此C3P0Config的初始化告一段落,C3P0Config首先初始化MultiPropertiesConfig,
再配置C3P0Config,加载com.mchange.v2.c3p0.cfg.finder类,如果没有,则通过
DefaultC3P0ConfigFinder初始化数据库先关属性,DefaultC3P0ConfigFinder首先加载
xml文件,如果没有,则从C3P0Defaults通过反射获取属性,构建C3P0Config。
总结:
从AbstractComboPooledDataSource初始化,我们可以看出,初始化就是创建数据源驱动管理器DriverManagerDataSource,创建数据库连接池WrapperConnectionPoolDataSource,初始化数据库连接池的数据源驱动管理器,然后,初始化AbstractComboPooledDataSource的WrapperConnectionPoolDataSource。从AbstractPoolBackedDataSource的构造可以看出主要是添加属性change监听器,当AbstractPoolBackedDataSource的属性值有变化时,重置连接池管理器。从PoolBackedDataSourceBase的构造函数中,可以看出,其主要初始化属性辅助工具,初始化数据源name,在初始化数据源name是用到了C3P0Config,C3P0Config的初始化,上面已总结。
//NamedScope
//PropertyChangeSupport
//Collections
//Class
C3P0 DriverManagerDataSource初始化:http://donald-draper.iteye.com/blog/2343564
WrapperConnectionPoolDataSource初始化:http://donald-draper.iteye.com/blog/2345008
C3P0属性设置和数据库连接池的获取:http://donald-draper.iteye.com/blog/2345084
在我们开发的时候经常会用到数据源,我们从数据源获取连接,今天我们就通过C3P0以探究竟。
测试主类:
import org.slf4j.LoggerFactory; import com.mchange.v2.c3p0.ComboPooledDataSource; public class testC3p0 { private static Logger log = LoggerFactory.getLogger(testC3p0.class); private static ComboPooledDataSource cpDSource =null; public static void main(String[] args){ initC3p0DataSource(); testC3p0BaseMysql(); } private static void initC3p0DataSource(){ Properties props = new Properties(); InputStream in = Thread.currentThread().getContextClassLoader().getResourceAsStream("c3p0.properties"); try { props.load(in); } catch (IOException e) { e.printStackTrace(); } finally{ try { in.close(); } catch (IOException e) { e.printStackTrace(); } } cpDSource = new ComboPooledDataSource(); try { cpDSource.setDriverClass(props.getProperty("driver")); log.info("=============driver:"+props.getProperty("driver")); cpDSource.setJdbcUrl(props.getProperty("url")); log.info("=============url:"+props.getProperty("url")); cpDSource.setUser(props.getProperty("user")); log.info("=============user:"+props.getProperty("user")); cpDSource.setPassword(props.getProperty("password")); log.info("=============password:"+props.getProperty("password")); cpDSource.setInitialPoolSize(5); cpDSource.setMaxPoolSize(30); cpDSource.setMinPoolSize(5); /*c3p0全局的PreparedStatements缓存的大小。 如果maxStatements与maxStatementsPerConnection均为0,则缓存不生效, 只要有一个不为0,则语句的缓存就能生效。如果默认值: 0*/ cpDSource.setMaxStatements(100); //最大空闲时间,60秒内未使用则连接被丢弃。若为0则永不丢弃。默认值: 0 cpDSource.setIdleConnectionTestPeriod(60); /*如果为false,则获取连接失败将会引起所有等待连接池来获取连接的线程抛出异常, 但是数据源仍有效保留,并在下次调用getConnection()的时候继续尝试获取连接。 如果设为true,那么在尝试获取连接失败后该数据源将申明已断开并永久关闭。默认: false*/ cpDSource.setBreakAfterAcquireFailure(false); //定义在从数据库获取新连接失败后重复尝试的次数。默认值: 30 ;小于等于0表示无限次 cpDSource.setAcquireRetryAttempts(30); cpDSource.setTestConnectionOnCheckout(false); } catch (PropertyVetoException e) { e.printStackTrace(); } log.info("========Init c3p0DSource end============="); } public static void testC3p0BaseMysql() { Connection con = null;// 创建一个数据库连接 PreparedStatement pre = null;// 创建预编译语句对象,一般都是用这个而不用Statement ResultSet result = null;// 创建一个结果集对象 try { con = cpDSource.getConnection(); String iSql = "INSERT INTO user(name,age)VALUES(?,?)"; PreparedStatement ps =con.prepareStatement(iSql); ps.setString(1, "jack"); ps.setInt(2, 23); ps.execute(); ps.setString(1, "mark"); ps.setInt(2, 67); ps.execute(); String uSql = "UPDATE user SET name = ?,age=? WHERE id=?"; ps = con.prepareStatement(uSql); ps.setString(1, "donald"); ps.setInt(2, 28); ps.setInt(3, 11); ps.executeUpdate(); } catch (Exception e) { log.error("============ERROR:"+e.getMessage()); e.printStackTrace(); } finally { try { if (result != null) result.close(); if (pre != null) pre.close(); if (con != null) con.close(); } catch (Exception e) { e.printStackTrace(); } } } }
我们从这一句来看
cpDSource = new ComboPooledDataSource();
//ComboPooledDataSource public final class ComboPooledDataSource extends AbstractComboPooledDataSource implements Serializable, Referenceable { private static final long serialVersionUID = 1L; private static final short VERSION = 2; public ComboPooledDataSource() { } } ComboPooledDataSource的构造函数没有做什么事情,查看其父类AbstractComboPooledDataSource //AbstractComboPooledDataSource public abstract class AbstractComboPooledDataSource extends AbstractPoolBackedDataSource implements PooledDataSource, Serializable, Referenceable { static final MLogger logger = MLog.getLogger(com/mchange/v2/c3p0/AbstractComboPooledDataSource); static final Set TO_STRING_IGNORE_PROPS = new HashSet(Arrays.asList(new String[] { "connection", "lastAcquisitionFailureDefaultUser", "lastCheckinFailureDefaultUser", "lastCheckoutFailureDefaultUser", "lastConnectionTestFailureDefaultUser", "lastIdleTestFailureDefaultUser", "logWriter", "loginTimeout", "numBusyConnections", "numBusyConnectionsAllUsers", "numBusyConnectionsDefaultUser", "numConnections", "numConnectionsAllUsers", "numConnectionsDefaultUser", "numFailedCheckinsDefaultUser", "numFailedCheckoutsDefaultUser", "numFailedIdleTestsDefaultUser", "numIdleConnections", "numIdleConnectionsAllUsers", "numThreadsAwaitingCheckoutDefaultUser", "numIdleConnectionsDefaultUser", "numUnclosedOrphanedConnections", "numUnclosedOrphanedConnectionsAllUsers", "numUnclosedOrphanedConnectionsDefaultUser", "numUserPools", "effectivePropertyCycleDefaultUser", "parentLogger", "startTimeMillisDefaultUser", "statementCacheNumCheckedOutDefaultUser", "statementCacheNumCheckedOutStatementsAllUsers", "statementCacheNumConnectionsWithCachedStatementsAllUsers", "statementCacheNumConnectionsWithCachedStatementsDefaultUser", "statementCacheNumStatementsAllUsers", "statementCacheNumStatementsDefaultUser", "statementDestroyerNumConnectionsInUseAllUsers", "statementDestroyerNumConnectionsWithDeferredDestroyStatementsAllUsers", "statementDestroyerNumDeferredDestroyStatementsAllUsers", "statementDestroyerNumConnectionsInUseDefaultUser", "statementDestroyerNumConnectionsWithDeferredDestroyStatementsDefaultUser", "statementDestroyerNumDeferredDestroyStatementsDefaultUser", "statementDestroyerNumThreads", "statementDestroyerNumActiveThreads", "statementDestroyerNumIdleThreads", "statementDestroyerNumTasksPending", "threadPoolSize", "threadPoolNumActiveThreads", "threadPoolNumIdleThreads", "threadPoolNumTasksPending", "threadPoolStackTraces", "threadPoolStatus", "overrideDefaultUser", "overrideDefaultPassword", "password", "reference", "upTimeMillisDefaultUser", "user", "userOverridesAsString", "allUsers", "connectionPoolDataSource", "propertyChangeListeners", "vetoableChangeListeners" })); transient DriverManagerDataSource dmds; transient WrapperConnectionPoolDataSource wcpds; private static final long serialVersionUID = 1L; private static final short VERSION = 1; //构造AbstractComboPooledDataSource public AbstractComboPooledDataSource() { this(true); } public AbstractComboPooledDataSource(boolean autoregister) { // super(autoregister); //新建驱动数据源管理器 dmds = new DriverManagerDataSource(); //新建数据库连接池 wcpds = new WrapperConnectionPoolDataSource(); //设置数据连接池的数据源驱动管理器 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(); } //设置数据库连接池 public synchronized void setConnectionPoolDataSource(ConnectionPoolDataSource connectionPoolDataSource) throws PropertyVetoException { ConnectionPoolDataSource oldVal = this.connectionPoolDataSource; if(!eqOrBothNull(oldVal, connectionPoolDataSource)) vcs.fireVetoableChange("connectionPoolDataSource", oldVal, connectionPoolDataSource); //初始化数据库连接池 this.connectionPoolDataSource = connectionPoolDataSource; if(!eqOrBothNull(oldVal, connectionPoolDataSource)) pcs.firePropertyChange("connectionPoolDataSource", oldVal, connectionPoolDataSource); } }
从AbstractComboPooledDataSource初始化,我们可以看出,
初始化就是创建数据源驱动管理器DriverManagerDataSource,
创建数据库连接池WrapperConnectionPoolDataSource,初始化数据库连接池的数据源驱动管理器,然后,初始化AbstractComboPooledDataSource的WrapperConnectionPoolDataSource。
再来看AbstractPoolBackedDataSource的构造
public abstract class AbstractPoolBackedDataSource extends PoolBackedDataSourceBase implements PooledDataSource { static final MLogger logger = MLog.getLogger(com/mchange/v2/c3p0/impl/AbstractPoolBackedDataSource); static final String NO_CPDS_ERR_MSG = "Attempted to use an uninitialized PoolBackedDataSource. Please call setConnectionPoolDataSource( ... ) to initialize."; //连接池管理器 transient C3P0PooledConnectionPoolManager poolManager; transient boolean is_closed; private static final long serialVersionUID = 1L; private static final short VERSION = 1; protected AbstractPoolBackedDataSource(boolean autoregister) { super(autoregister); is_closed = false; setUpPropertyEvents(); } //添加属性Change监听器 private void setUpPropertyEvents() { PropertyChangeListener l = new PropertyChangeListener() { public void propertyChange(PropertyChangeEvent evt) { resetPoolManager(false); } final AbstractPoolBackedDataSource this$0; { this.this$0 = AbstractPoolBackedDataSource.this; super(); } }; addPropertyChangeListener(l); } //重置连接池管理器 public synchronized void resetPoolManager(boolean close_checked_out_connections) { if(poolManager != null) { poolManager.close(close_checked_out_connections); poolManager = null; } } //添加属性Change监听器 public void addPropertyChangeListener(PropertyChangeListener pcl) { pcs.addPropertyChangeListener(pcl); } public boolean isWrapperFor(Class iface) throws SQLException { return isWrapperForThis(iface); } public Object unwrap(Class iface) throws SQLException { if(isWrapperForThis(iface)) return this; else throw new SQLException((new StringBuilder()).append(this).append(" is not a wrapper for or implementation of ").append(iface.getName()).toString()); } protected final boolean isWrapperForThis(Class iface) { return iface.isAssignableFrom(getClass()); } public boolean isWrapperFor(Class iface) throws SQLException { return isWrapperForThis(iface); } }
从AbstractPoolBackedDataSource的构造可以看出主要是添加属性change监听器,当AbstractPoolBackedDataSource的
属性值有变化时,重置连接池管理器。
//C3P0PooledConnectionPoolManager
public final class C3P0PooledConnectionPoolManager { private static final MLogger logger = MLog.getLogger(com/mchange/v2/c3p0/impl/C3P0PooledConnectionPoolManager); private static final boolean POOL_EVENT_SUPPORT = false; private static final CoalesceChecker COALESCE_CHECKER; static final Coalescer COALESCER; static final int DFLT_NUM_TASK_THREADS_PER_DATA_SOURCE = 3; ThreadPoolAsynchronousRunner taskRunner; ThreadPoolAsynchronousRunner deferredStatementDestroyer; Timer timer; ResourcePoolFactory rpfact; Map authsToPools; //数据源连接池 final ConnectionPoolDataSource cpds; final Map propNamesToReadMethods; final Map flatPropertyOverrides; final Map userOverrides; final DbAuth defaultAuth; final String parentDataSourceIdentityToken; final String parentDataSourceName; int num_task_threads; static { COALESCE_CHECKER = IdentityTokenizedCoalesceChecker.INSTANCE; COALESCER = CoalescerFactory.createCoalescer(COALESCE_CHECKER, true, false); } }
再来看PoolBackedDataSourceBase的构造:
public class PoolBackedDataSourceBase extends IdentityTokenResolvable implements Referenceable, Serializable { //java bean 属性改变事件辅助工具 protected PropertyChangeSupport pcs; protected VetoableChangeSupport vcs; //数据库连接池 private ConnectionPoolDataSource connectionPoolDataSource; private String dataSourceName; private Map extensions; private String factoryClassLocation; private volatile String identityToken; private int numHelperThreads; 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("connectionPoolDataSource"); referenceMaker.addReferenceProperty("dataSourceName"); referenceMaker.addReferenceProperty("extensions"); referenceMaker.addReferenceProperty("factoryClassLocation"); referenceMaker.addReferenceProperty("identityToken"); referenceMaker.addReferenceProperty("numHelperThreads"); } public PoolBackedDataSourceBase(boolean autoregister) { //初始化属性辅助工具 pcs = new PropertyChangeSupport(this); vcs = new VetoableChangeSupport(this); //初始化数据源name dataSourceName = C3P0Config.initializeStringPropertyVar("dataSourceName", C3P0Defaults.dataSourceName()); extensions = C3P0Config.initializeExtensions(); factoryClassLocation = C3P0Config.initializeStringPropertyVar("factoryClassLocation", C3P0Defaults.factoryClassLocation()); numHelperThreads = C3P0Config.initializeIntPropertyVar("numHelperThreads", C3P0Defaults.numHelperThreads()); if(autoregister) { identityToken = C3P0ImplUtils.allocateIdentityToken(this); C3P0Registry.reregister(this); } } }
从上面可以看出,PoolBackedDataSourceBase的构造函数中,主要初始化属性辅助工具,初始化数据源name
//C3P0配置项
public final class C3P0Config { static final String PROP_STYLE_NAMED_CFG_PFX = "c3p0.named-configs"; static final int PROP_STYLE_NAMED_CFG_PFX_LEN = "c3p0.named-configs".length(); static final String PROP_STYLE_USER_OVERRIDES_PART = "user-overrides"; static final String PROP_STYLE_USER_OVERRIDES_PFX = "c3p0.user-overrides"; static final int PROP_STYLE_USER_OVERRIDES_PFX_LEN = "c3p0.user-overrides".length(); static final String PROP_STYLE_EXTENSIONS_PART = "extensions"; static final String PROP_STYLE_EXTENSIONS_PFX = "c3p0.extensions"; static final int PROP_STYLE_EXTENSIONS_PFX_LEN = "c3p0.extensions".length(); public static final String CFG_FINDER_CLASSNAME_KEY = "com.mchange.v2.c3p0.cfg.finder"; public static final String DEFAULT_CONFIG_NAME = "default"; //配置文件 public static final String PROPS_FILE_RSRC_PATH = "/c3p0.properties"; static final MLogger logger = MLog.getLogger(com/mchange/v2/c3p0/cfg/C3P0Config); //配置文件属性操作工具 private static MultiPropertiesConfig _MPCONFIG; //C3P0配置类 private static C3P0Config _MAIN; static final Class SUOAS_ARGS[] = { java/lang/String }; static final Collection SKIP_BIND_PROPS = Arrays.asList(new String[] { "loginTimeout", "properties" }); NamedScope defaultConfig;//默认配置 HashMap configNamesToNamedScopes;//命名空间下的配置名 static { //设置配置文件工具类 setLibraryMultiPropertiesConfig(findLibraryMultiPropertiesConfig()); //设置C3P0Config setMainConfig(findLibraryC3P0Config(false)); warnOnUnknownProperties(MAIN()); } //加载配置文件 private static MultiPropertiesConfig findLibraryMultiPropertiesConfig() { String defaults[] = { "/mchange-commons.properties", "/mchange-log.properties" }; String preempts[] = { "hocon:/reference,/application,/c3p0,/", "/c3p0.properties", "/" }; return MConfig.readVmConfig(defaults, preempts); } //设置配置文件工具类 private static synchronized void setLibraryMultiPropertiesConfig(MultiPropertiesConfig mpc) { _MPCONFIG = mpc; } //设置C3P0Config public static synchronized void setMainConfig(C3P0Config protoMain) { _MAIN = protoMain; } //初始化propKey对应的值 public static String initializeStringPropertyVar(String propKey, String dflt) { String out = getUnspecifiedUserProperty(propKey, null); if(out == null) out = dflt; return out; } //获取propKey对应的属性 public static String getUnspecifiedUserProperty(String propKey, String configName) { String out = null; if(configName == null) { out = (String)MAIN().defaultConfig.props.get(propKey); } else { NamedScope named = (NamedScope)MAIN().configNamesToNamedScopes.get(configName); if(named != null) out = (String)named.props.get(propKey); else logger.warning((new StringBuilder()).append("named-config with name '").append(configName).append("' does not exist. Using default-config for property '").append(propKey).append("'.").toString()); if(out == null) out = (String)MAIN().defaultConfig.props.get(propKey); } return out; } }
来看C3P0Config的findLibraryC3P0Config函数
//C3P0Config,初始化C3P0Config
private static C3P0Config findLibraryC3P0Config(boolean warn_on_conflicting_overrides) { String cname = MPCONFIG().getProperty("com.mchange.v2.c3p0.cfg.finder"); C3P0ConfigFinder cfgFinder = null; try { if(cname != null) //加载com.mchange.v2.c3p0.cfg.finder类 cfgFinder = (C3P0ConfigFinder)Class.forName(cname).newInstance(); } catch(Exception e) { if(logger.isLoggable(MLevel.WARNING)) logger.log(MLevel.WARNING, (new StringBuilder()).append("Could not load specified C3P0ConfigFinder class'").append(cname).append("'.").toString(), e); } C3P0Config protoMain; try { if(cfgFinder == null) { Class.forName("org.w3c.dom.Node"); Class.forName("com.mchange.v2.c3p0.cfg.C3P0ConfigXmlUtils"); //如果配置发现类不存在,则创建默认的DefaultC3P0ConfigFinder为cfgFinder cfgFinder = new DefaultC3P0ConfigFinder(warn_on_conflicting_overrides); } //发现配置文件 protoMain = cfgFinder.findConfig(); } catch(Exception e) { if(logger.isLoggable(MLevel.WARNING)) logger.log(MLevel.WARNING, "XML configuration disabled! Verify that standard XML libs are available.", e); HashMap flatDefaults = C3P0ConfigUtils.extractHardcodedC3P0Defaults(); flatDefaults.putAll(C3P0ConfigUtils.extractC3P0PropertiesResources()); protoMain = C3P0ConfigUtils.configFromFlatDefaults(flatDefaults); } //获取属性命令空间 HashMap propStyleConfigNamesToNamedScopes = findPropStyleNamedScopes(); HashMap cfgFoundConfigNamesToNamedScopes = protoMain.configNamesToNamedScopes; //最总的命名空间属性集 HashMap mergedConfigNamesToNamedScopes = new HashMap(); HashSet allConfigNames = new HashSet(cfgFoundConfigNamesToNamedScopes.keySet()); allConfigNames.addAll(propStyleConfigNamesToNamedScopes.keySet()); for(Iterator ii = allConfigNames.iterator(); ii.hasNext();) { String cfgName = (String)ii.next(); //将属性添加到对应的NameScope下 NamedScope cfgFound = (NamedScope)cfgFoundConfigNamesToNamedScopes.get(cfgName); NamedScope propStyle = (NamedScope)propStyleConfigNamesToNamedScopes.get(cfgName); //整合命名空间下的值 if(cfgFound != null && propStyle != null) mergedConfigNamesToNamedScopes.put(cfgName, cfgFound.mergedOver(propStyle)); else if(cfgFound != null && propStyle == null) mergedConfigNamesToNamedScopes.put(cfgName, cfgFound); else if(cfgFound == null && propStyle != null) mergedConfigNamesToNamedScopes.put(cfgName, propStyle); else throw new AssertionError("Huh? allConfigNames is the union, every name should be in one of the two maps."); } HashMap propStyleUserOverridesDefaultConfig = findPropStyleUserOverridesDefaultConfig(); HashMap propStyleExtensionsDefaultConfig = findPropStyleExtensionsDefaultConfig(); //创建命名空间 NamedScope mergedDefaultConfig = new NamedScope(protoMain.defaultConfig.props, NamedScope.mergeUserNamesToOverrides(protoMain.defaultConfig.userNamesToOverrides, propStyleUserOverridesDefaultConfig), NamedScope.mergeExtensions(protoMain.defaultConfig.extensions, propStyleExtensionsDefaultConfig)); //创建C3P0Config,并返回 return new C3P0Config(mergedDefaultConfig, mergedConfigNamesToNamedScopes); }
来看一下DefaultC3P0ConfigFinder如何获取配置C3P0Config
//发现配置文件
protoMain = cfgFinder.findConfig();
//DefaultC3P0ConfigFinder
public C3P0Config findConfig() throws Exception { C3P0Config out; HashMap flatDefaults; String cfgFile; InputStream is; //加载c3p0默认配置从硬编码中C3P0Defaults(c3p0默认配置类) flatDefaults = C3P0ConfigUtils.extractHardcodedC3P0Defaults(); flatDefaults.putAll(C3P0ConfigUtils.extractC3P0PropertiesResources()); //加载xml配置文件 cfgFile = C3P0Config.getPropsFileConfigProperty("com.mchange.v2.c3p0.cfg.xml"); if(cfgFile == null) { //从xml文件中,解析配置 C3P0Config xmlConfig = C3P0ConfigXmlUtils.extractXmlConfigFromDefaultResource(); if(xmlConfig != null) { insertDefaultsUnderNascentConfig(flatDefaults, xmlConfig); out = xmlConfig; mbOverrideWarning("resource", "/c3p0-config.xml"); } else { //如果xml文件不存在,则从C3P0Defaults获取默认属性 out = C3P0ConfigUtils.configFromFlatDefaults(flatDefaults); } break MISSING_BLOCK_LABEL_286; } java.util.Properties sysPropConfig = C3P0ConfigUtils.findAllC3P0SystemProperties(); out.defaultConfig.props.putAll(sysPropConfig); return out; }
来看这一句
//如果xml文件不存在,则从C3P0Defaults获取默认属性
out = C3P0ConfigUtils.configFromFlatDefaults(flatDefaults);
//C3P0ConfigUtils
根据C3P0Defaults默认属性,配置C3P0Config
public static C3P0Config configFromFlatDefaults(HashMap flatDefaults) { NamedScope defaults = new NamedScope(); defaults.props.putAll(flatDefaults); HashMap configNamesToNamedScopes = new HashMap(); return new C3P0Config(defaults, configNamesToNamedScopes); }
至此C3P0Config的初始化告一段落,C3P0Config首先初始化MultiPropertiesConfig,
再配置C3P0Config,加载com.mchange.v2.c3p0.cfg.finder类,如果没有,则通过
DefaultC3P0ConfigFinder初始化数据库先关属性,DefaultC3P0ConfigFinder首先加载
xml文件,如果没有,则从C3P0Defaults通过反射获取属性,构建C3P0Config。
总结:
从AbstractComboPooledDataSource初始化,我们可以看出,初始化就是创建数据源驱动管理器DriverManagerDataSource,创建数据库连接池WrapperConnectionPoolDataSource,初始化数据库连接池的数据源驱动管理器,然后,初始化AbstractComboPooledDataSource的WrapperConnectionPoolDataSource。从AbstractPoolBackedDataSource的构造可以看出主要是添加属性change监听器,当AbstractPoolBackedDataSource的属性值有变化时,重置连接池管理器。从PoolBackedDataSourceBase的构造函数中,可以看出,其主要初始化属性辅助工具,初始化数据源name,在初始化数据源name是用到了C3P0Config,C3P0Config的初始化,上面已总结。
//NamedScope
package com.mchange.v2.c3p0.cfg; import java.util.*; class NamedScope { HashMap props;//属性集 HashMap userNamesToOverrides; HashMap extensions;//扩展 NamedScope() { props = new HashMap(); userNamesToOverrides = new HashMap(); extensions = new HashMap(); } NamedScope(HashMap props, HashMap userNamesToOverrides, HashMap extensions) { this.props = props; this.userNamesToOverrides = userNamesToOverrides; this.extensions = extensions; } //覆盖原始属性集 NamedScope mergedOver(NamedScope underScope) { HashMap mergedProps = (HashMap)underScope.props.clone(); mergedProps.putAll(props); HashMap mergedUserNamesToOverrides = mergeUserNamesToOverrides(userNamesToOverrides, underScope.userNamesToOverrides); HashMap mergedExtensions = mergeExtensions(extensions, underScope.extensions); return new NamedScope(mergedProps, mergedUserNamesToOverrides, mergedExtensions); } //覆盖扩展集 static HashMap mergeExtensions(HashMap over, HashMap under) { HashMap out = (HashMap)under.clone(); out.putAll(over); return out; } static HashMap mergeUserNamesToOverrides(HashMap over, HashMap under) { HashMap out = (HashMap)under.clone(); HashSet underUserNames = new HashSet(under.keySet()); HashSet overUserNames = new HashSet(over.keySet()); HashSet newUserNames = (HashSet)overUserNames.clone(); newUserNames.removeAll(underUserNames); String name; for(Iterator ii = newUserNames.iterator(); ii.hasNext(); out.put(name, ((HashMap)over.get(name)).clone())) name = (String)ii.next(); HashSet mergeUserNames = (HashSet)overUserNames.clone(); mergeUserNames.retainAll(underUserNames); String name; for(Iterator ii = mergeUserNames.iterator(); ii.hasNext(); ((HashMap)out.get(name)).putAll((HashMap)over.get(name))) name = (String)ii.next(); return out; } } //MultiPropertiesConfig public abstract class MultiPropertiesConfig implements PropertiesConfig { public MultiPropertiesConfig() { } /** * @deprecated Method readVmConfig is deprecated */ public static MultiPropertiesConfig readVmConfig(String as[], String as1[]) { return ConfigUtils.readVmConfig(as, as1); } /** * @deprecated Method readVmConfig is deprecated */ public static MultiPropertiesConfig readVmConfig() { return ConfigUtils.readVmConfig(); } public static MultiPropertiesConfig fromProperties(String s, Properties properties) { return new BasicMultiPropertiesConfig(s, properties); } public static MultiPropertiesConfig fromProperties(Properties properties) { return fromProperties(PROGRAMMATICALLY_SUPPLIED_PROPERTIES, properties); } public abstract String[] getPropertiesResourcePaths(); public abstract Properties getPropertiesByResourcePath(String s); public abstract Properties getPropertiesByPrefix(String s); public abstract String getProperty(String s); public abstract List getDelayedLogItems(); private static String PROGRAMMATICALLY_SUPPLIED_PROPERTIES = "PROGRAMMATICALLY_SUPPLIED_PROPERTIES"; }
public final class C3P0Defaults { private static final int MAX_STATEMENTS = 0; private static final int MAX_STATEMENTS_PER_CONNECTION = 0; private static final int INITIAL_POOL_SIZE = 3; private static final int MIN_POOL_SIZE = 3; private static final int MAX_POOL_SIZE = 15; private static final int IDLE_CONNECTION_TEST_PERIOD = 0; private static final int MAX_IDLE_TIME = 0; private static final int PROPERTY_CYCLE = 0; private static final int ACQUIRE_INCREMENT = 3; private static final int ACQUIRE_RETRY_ATTEMPTS = 30; private static final int ACQUIRE_RETRY_DELAY = 1000; private static final int CHECKOUT_TIMEOUT = 0; private static final int MAX_ADMINISTRATIVE_TASK_TIME = 0; private static final int MAX_IDLE_TIME_EXCESS_CONNECTIONS = 0; private static final int MAX_CONNECTION_AGE = 0; private static final int UNRETURNED_CONNECTION_TIMEOUT = 0; private static final int STATEMENT_CACHE_NUM_DEFERRED_CLOSE_THREADS = 0; private static final boolean BREAK_AFTER_ACQUIRE_FAILURE = false; private static final boolean TEST_CONNECTION_ON_CHECKOUT = false; private static final boolean TEST_CONNECTION_ON_CHECKIN = false; private static final boolean AUTO_COMMIT_ON_CLOSE = false; private static final boolean FORCE_IGNORE_UNRESOLVED_TXNS = false; private static final boolean USES_TRADITIONAL_REFLECTIVE_PROXIES = false; private static final boolean DEBUG_UNRETURNED_CONNECTION_STACK_TRACES = false; private static final boolean PRIVILEGE_SPAWNED_THREADS = false; private static final boolean FORCE_USE_NAMED_DRIVER_CLASS = false; private static final boolean FORCE_SYNCHRONOUS_CHECKINS = false; private static final int NUM_HELPER_THREADS = 3; private static final String AUTOMATIC_TEST_TABLE = null; private static final String CONNECTION_CUSTOMIZER_CLASS_NAME = null; private static final String CONNECTION_TESTER_CLASS_NAME = "com.mchange.v2.c3p0.impl.DefaultConnectionTester"; private static final String CONTEXT_CLASS_LOADER_SOURCE = "caller"; private static final String DRIVER_CLASS = null; private static final String JDBC_URL = null; private static final String OVERRIDE_DEFAULT_USER = null; private static final String OVERRIDE_DEFAULT_PASSWORD = null; private static final String PASSWORD = null; private static final String PREFERRED_TEST_QUERY = null; private static final String FACTORY_CLASS_LOCATION = null; private static final String USER_OVERRIDES_AS_STRING = null; private static final String USER = null; private static final String DATA_SOURCE_NAME = null; private static final Map EXTENSIONS = Collections.emptyMap(); private static final Set KNOWN_PROPERTIES; static { Method methods[] = com/mchange/v2/c3p0/impl/C3P0Defaults.getMethods(); Set s = new HashSet(); int i = 0; for(int len = methods.length; i < len; i++) { Method m = methods[i]; if(Modifier.isStatic(m.getModifiers()) && m.getParameterTypes().length == 0) s.add(m.getName()); } KNOWN_PROPERTIES = Collections.unmodifiableSet(s); } }
//PropertyChangeSupport
package java.beans; import java.io.Serializable; import java.io.ObjectStreamField; import java.io.ObjectOutputStream; import java.io.ObjectInputStream; import java.io.IOException; import java.util.Hashtable; import java.util.Map.Entry; /** * This is a utility class that can be used by beans that support bound * 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 PropertyChangeListener} can be registered for all properties * or for a property specified by name. * <p> * Here is an example of {@code PropertyChangeSupport} usage that follows * the rules and recommendations laid out in the JavaBeans™ specification: * <pre> * public class MyBean { * private final PropertyChangeSupport pcs = new PropertyChangeSupport(this); * * public void addPropertyChangeListener(PropertyChangeListener listener) { * this.pcs.addPropertyChangeListener(listener); * } * * public void removePropertyChangeListener(PropertyChangeListener listener) { * this.pcs.removePropertyChangeListener(listener); * } * * private String value; * * public String getValue() { * return this.value; * } * * public void setValue(String newValue) { * String oldValue = this.value; * this.value = newValue; * this.pcs.firePropertyChange("value", oldValue, newValue); * } * * [...] * } * </pre> * <p> * A {@code PropertyChangeSupport} 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 VetoableChangeSupport */ public class PropertyChangeSupport implements Serializable { private PropertyChangeListenerMap map = new PropertyChangeListenerMap(); /** * Constructs a <code>PropertyChangeSupport</code> object. * * @param sourceBean The bean to be given as the source for any events. */ public PropertyChangeSupport(Object sourceBean) { if (sourceBean == null) { throw new NullPointerException(); } source = sourceBean; } /** * Add a PropertyChangeListener 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 PropertyChangeListener to be added */ public void addPropertyChangeListener(PropertyChangeListener listener) { if (listener == null) { return; } if (listener instanceof PropertyChangeListenerProxy) { PropertyChangeListenerProxy proxy = (PropertyChangeListenerProxy)listener; // Call two argument add method. addPropertyChangeListener(proxy.getPropertyName(), proxy.getListener()); } else { this.map.add(null, listener); } } }
//Collections
/** * Returns the empty map (immutable). This map is serializable. * * <p>This example illustrates the type-safe way to obtain an empty set: * <pre> * Map<String, Date> s = Collections.emptyMap(); * </pre> * Implementation note: Implementations of this method need not * create a separate <tt>Map</tt> object for each call. Using this * method is likely to have comparable cost to using the like-named * field. (Unlike this method, the field does not provide type safety.) * * @see #EMPTY_MAP * @since 1.5 */ @SuppressWarnings("unchecked") public static final <K,V> Map<K,V> emptyMap() { return (Map<K,V>) EMPTY_MAP; } /** * Returns an unmodifiable view of the specified set. This method allows * modules to provide users with "read-only" access to internal sets. * Query operations on the returned set "read through" to the specified * set, and attempts to modify the returned set, whether direct or via its * iterator, result in an <tt>UnsupportedOperationException</tt>.<p> * * The returned set will be serializable if the specified set * is serializable. * * @param s the set for which an unmodifiable view is to be returned. * @return an unmodifiable view of the specified set. */ public static <T> Set<T> unmodifiableSet(Set<? extends T> s) { return new UnmodifiableSet<>(s); }
//Class
/** * Determines if the class or interface represented by this * {@code Class} object is either the same as, or is a superclass or * superinterface of, the class or interface represented by the specified * {@code Class} parameter. It returns {@code true} if so; * otherwise it returns {@code false}. If this {@code Class} * object represents a primitive type, this method returns * {@code true} if the specified {@code Class} parameter is * exactly this {@code Class} object; otherwise it returns * {@code false}. * * <p> Specifically, this method tests whether the type represented by the * specified {@code Class} parameter can be converted to the type * represented by this {@code Class} object via an identity conversion * or via a widening reference conversion. See [i]The Java Language * Specification[/i], sections 5.1.1 and 5.1.4 , for details. * * @param cls the {@code Class} object to be checked * @return the {@code boolean} value indicating whether objects of the * type {@code cls} can be assigned to objects of this class * @exception NullPointerException if the specified Class parameter is * null. * @since JDK1.1 */ public native boolean isAssignableFrom(Class<?> cls);
发表评论
-
C3P0数据连接的获取,预编译,查询
2016-12-15 18:21 969C3P0 ComboPooledDataSource初始化:h ... -
C3P0属性设置和数据库连接池的获取
2016-12-15 16:45 3309C3P0 ComboPooledDataSource初始化:h ... -
WrapperConnectionPoolDataSource初始化
2016-12-15 10:27 1214C3P0 ComboPooledDataSource初始化:h ... -
C3P0 DriverManagerDataSource初始化
2016-12-08 16:11 2045WeakHashMap:http://mikewang.blo ...
相关推荐
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"> <!-- 其他参数配置... --> ``` 理解并正确配置这些参数,是确保C3P0连接池在你的Java应用程序中高效运行的关键步骤。在...
1. `minPoolSize`:最小连接池大小,即系统启动时初始化的连接数量。 2. `maxPoolSize`:最大连接池大小,超过这个数量,新的请求将等待现有连接释放。 3. `maxIdleTime`:连接的最大空闲时间,超过这个时间未被使用...
1. **连接初始化**:当应用程序启动时,C3P0会根据配置参数预先创建一定数量的数据库连接,放入连接池。 2. **连接获取**:当需要访问数据库时,应用程序从连接池中借用一个连接,而不是直接创建新的连接。 3. **...
3. **初始化C3P0**:在代码中创建` ComboPooledDataSource `对象,并加载配置,或者在Spring等框架中通过XML或注解方式配置C3P0数据源。 4. **获取与释放连接**:使用`getConnection()`方法从数据源获取连接,使用...
- 创建数据源:通过`com.mchange.v2.c3p0.ComboPooledDataSource`类创建数据源对象,并设置相关属性。 - 获取与释放连接:使用数据源提供的方法获取和归还数据库连接。 5. **最佳实践**: - 调整参数:根据应用...
在描述中提到的三个jar包,c3p0-0.9.1.jar、c3p0-0.9.1.2.jar和c3p0-0.9.1-pre6.jar,都是C3P0的不同版本。通常,你需要的是最新版本,以获取最新的功能和修复的bug。例如,c3p0-0.9.1.2.jar比c3p0-0.9.1.jar更新,...
例如,通过C3P0初始化一个数据库连接池,然后在DBUtils的QueryRunner中使用这些连接来执行数据库操作。这样,不仅可以利用C3P0的连接池管理,还能享受DBUtils带来的简洁和安全的数据库操作接口。 以下是一个简单的...
3. **初始化数据源**:使用`com.mchange.v2.c3p0.ComboPooledDataSource`类创建数据源实例,加载配置信息。 4. **获取和释放连接**:通过数据源的`getConnection()`方法获取数据库连接,使用完毕后通过`close()`...
3. 在代码中初始化C3P0的数据源,如` ComboPooledDataSource cpds = new ComboPooledDataSource();` 4. 配置数据源,加载配置文件,如`cpds.setConfigFile("/path/to/c3p0-config.xml");` 5. 通过数据源获取数据库...
3. **性能优化**:C3P0提供了许多配置参数,如最小、最大连接数,初始化连接数,连接获取超时等,可以根据实际需求调整,以实现最佳性能和资源利用。 4. **线程安全**:C3P0的设计是线程安全的,可以在多线程环境下...
1. **连接池**:数据库连接池在初始化时会创建一定数量的数据库连接,当应用程序需要访问数据库时,可以从连接池中获取一个已存在的连接,而不是每次请求都创建新的连接,使用完毕后归还到连接池,而不是关闭连接。...
- `initialPoolSize`:初始化时的连接数。 - `acquireIncrement`:当连接池需要更多连接时,每次获取的连接数量。 - `idleConnectionTestPeriod`:检测空闲连接的时间间隔,防止死连接。 - `...
3. 在你的代码中,通过` ComboPooledDataSource `类实例化C3P0数据源,并设置配置文件路径。 4. 获取数据库连接,使用后归还到连接池。 总的来说,C3P0连接池是Java开发中实现数据库连接管理的重要工具,这两个JAR...
2. 配置文件:C3P0的配置通常在`c3p0-config.xml`文件中进行,包括数据源的基本信息(如数据库URL、用户名、密码)、连接池的初始化参数(如初始连接数、最大连接数)以及性能设置(如测试连接的SQL语句、超时时间等...
- **连接配置**:c3p0提供了丰富的配置参数,如最小连接数、最大连接数、初始化连接数、超时时间等,允许开发者根据实际需求灵活调整。 2. **c3p0工作原理** - **初始化**:应用启动时,c3p0会根据配置创建指定...
3. **初始化连接池**:在Java代码中,通过`com.mchange.v2.c3p0.ComboPooledDataSource`类创建连接池实例,并根据配置信息初始化。 4. **获取与释放连接**:使用`getConnection()`方法从连接池获取连接,使用完毕后...
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"> <!-- 其他配置属性 --> ``` 配置参数包括但不限于: - `minPoolSize`:最小连接数。 - `maxPoolSize`:最大连接数。 - `...
4. **配置灵活性**:C3p0允许用户通过配置文件(如c3p0.properties)或代码方式设置各种参数,如初始化连接数、最小空闲连接数、最大连接数、超时时间等,以适应不同应用场景的需求。 5. **异常处理**:当数据库...
在使用C3P0时,开发者通常需要配置这个类的相关属性,如初始化连接数、最大连接数、超时时间等。例如,在DBManager.java中,可以通过以下方式设置这些参数: ```java import ...
// 初始化连接数 dataSource.setMaxPoolSize(20); // 最大连接数 dataSource.setMinPoolSize(2); // 最小连接数 dataSource.setMaxIdleTime(600); // 连接的最大空闲时间(秒) } } ``` 3. **使用C3P0数据源**...