1 // Set up any DataSources
2 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3
4 String[] dsNames = cfg.getPropertyGroups(PROP_DATASOURCE_PREFIX);
5 for (int i = 0; i < dsNames.length; i++) {
6 PropertiesParser pp = new PropertiesParser(cfg.getPropertyGroup(
7 PROP_DATASOURCE_PREFIX + "." + dsNames, true));
8
9 String cpClass = pp.getStringProperty(PROP_CONNECTION_PROVIDER_CLASS, null);
10
11 // custom connectionProvider...
12 if(cpClass != null) {
13 ConnectionProvider cp = null;
14 try {
15 cp = (ConnectionProvider) loadHelper.loadClass(cpClass).newInstance();
16 } catch (Exception e) {
17 initException = new SchedulerException("ConnectionProvider class '" + cpClass
18 + "' could not be instantiated.", e);
19 throw initException;
20 }
21
22 try {
23 // remove the class name, so it isn't attempted to be set
24 pp.getUnderlyingProperties().remove(
25 PROP_CONNECTION_PROVIDER_CLASS);
26
27 setBeanProps(cp, pp.getUnderlyingProperties());
28 cp.initialize();
29 } catch (Exception e) {
30 initException = new SchedulerException("ConnectionProvider class '" + cpClass
31 + "' props could not be configured.", e);
32 throw initException;
33 }
34
35 dbMgr = DBConnectionManager.getInstance();
36 dbMgr.addConnectionProvider(dsNames, cp);
37 } else {
38 String dsJndi = pp.getStringProperty(PROP_DATASOURCE_JNDI_URL, null);
39
40 if (dsJndi != null) {
41 boolean dsAlwaysLookup = pp.getBooleanProperty(
42 PROP_DATASOURCE_JNDI_ALWAYS_LOOKUP);
43 String dsJndiInitial = pp.getStringProperty(
44 PROP_DATASOURCE_JNDI_INITIAL);
45 String dsJndiProvider = pp.getStringProperty(
46 PROP_DATASOURCE_JNDI_PROVDER);
47 String dsJndiPrincipal = pp.getStringProperty(
48 PROP_DATASOURCE_JNDI_PRINCIPAL);
49 String dsJndiCredentials = pp.getStringProperty(
50 PROP_DATASOURCE_JNDI_CREDENTIALS);
51 Properties props = null;
52 if (null != dsJndiInitial || null != dsJndiProvider
53 || null != dsJndiPrincipal || null != dsJndiCredentials) {
54 props = new Properties();
55 if (dsJndiInitial != null) {
56 props.put(PROP_DATASOURCE_JNDI_INITIAL,
57 dsJndiInitial);
58 }
59 if (dsJndiProvider != null) {
60 props.put(PROP_DATASOURCE_JNDI_PROVDER,
61 dsJndiProvider);
62 }
63 if (dsJndiPrincipal != null) {
64 props.put(PROP_DATASOURCE_JNDI_PRINCIPAL,
65 dsJndiPrincipal);
66 }
67 if (dsJndiCredentials != null) {
68 props.put(PROP_DATASOURCE_JNDI_CREDENTIALS,
69 dsJndiCredentials);
70 }
71 }
72 JNDIConnectionProvider cp = new JNDIConnectionProvider(dsJndi,
73 props, dsAlwaysLookup);
74 dbMgr = DBConnectionManager.getInstance();
75 dbMgr.addConnectionProvider(dsNames, cp);
76 } else {
77 String dsDriver = pp.getStringProperty(PoolingConnectionProvider.DB_DRIVER);
78 String dsURL = pp.getStringProperty(PoolingConnectionProvider.DB_URL);
79
80 if (dsDriver == null) {
81 initException = new SchedulerException(
82 "Driver not specified for DataSource: "
83 + dsNames);
84 throw initException;
85 }
86 if (dsURL == null) {
87 initException = new SchedulerException(
88 "DB URL not specified for DataSource: "
89 + dsNames);
90 throw initException;
91 }
92 try {
93 PoolingConnectionProvider cp = new PoolingConnectionProvider(pp.getUnderlyingProperties());
94 dbMgr = DBConnectionManager.getInstance();
95 dbMgr.addConnectionProvider(dsNames, cp);
96 } catch (SQLException sqle) {
97 initException = new SchedulerException(
98 "Could not initialize DataSource: " + dsNames,
99 sqle);
100 throw initException;
101 }
102 }
103
104 }
105
106 }
从上面这段源码可以看出,如果在quartz.properties配置文件中没有设置PROP_CONNECTION_PROVIDER_CLASS或PROP_DATASOURCE_JNDI_URL项的话,则会使用默认的连接池PoolingConnectionProvider。那PoolingConnectionProvider中使用的是什么连接池呢?我们可以看看PoolingConnectionProvider的描述和实现:
1 /**
2 * <p>
3 * A <code>ConnectionProvider</code> implementation that creates its own
4 * pool of connections.
5 * </p>
6 *
7 * <p>
8 * This class uses C3PO (http://www.mchange.com/projects/c3p0/index.html) as
9 * the underlying pool implementation.</p>
10 *
11 * @see DBConnectionManager
12 * @see ConnectionProvider
13 *
14 * @author Sharada Jambula
15 * @author James House
16 * @author Mohammad Rezaei
17 */
18 public class PoolingConnectionProvider implements ConnectionProvider
从类描述中我们就可以看出,该类使用的是C3P0的连接池技术,也就是说Quartz2.2.0默认使用的是C3P0连接池。然后我们看到该类实现了ConnectionProvider接口,首先看看ConnectionProvider的接口定义:
1 /**
2 * Implementations of this interface used by <code>DBConnectionManager</code>
3 * to provide connections from various sources.
4 *
5 * @see DBConnectionManager
6 * @see PoolingConnectionProvider
7 * @see JNDIConnectionProvider
8 * @see org.quartz.utils.weblogic.WeblogicConnectionProvider
9 *
10 * @author Mohammad Rezaei
11 */
12 public interface ConnectionProvider {
13 /*
14 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
15 *
16 * Interface.
17 *
18 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
19 */
20
21 /**
22 * @return connection managed by this provider
23 * @throws SQLException
24 */
25 Connection getConnection() throws SQLException;
26
27
28 void shutdown() throws SQLException;
29
30 void initialize() throws SQLException;
31 }
View Code 从接口的描述可以知道,只需要实现该类,然后使用自定义的连接池技术就可以解决文中开头提到的问题了。
思路明确后,我们开始实现,我依照PoolingConnectionProvider的实现写了写了我自己的dbcp连接池的实现类,代码如下:
initialize方法:
1 private void initialize(
2 String dbDriver,
3 String dbURL,
4 String dbUser,
5 String dbPassword,
6 int maxConnections,
7 int maxStatementsPerConnection,
8 String dbValidationQuery,
9 boolean validateOnCheckout,
10 int idleValidationSeconds,
11 int maxIdleSeconds) throws SQLException, SchedulerException {
12 if (dbURL == null) {
13 throw new SQLException(
14 "DBPool could not be created: DB URL cannot be null");
15 }
16
17 if (dbDriver == null) {
18 throw new SQLException(
19 "DBPool '" + dbURL + "' could not be created: " +
20 "DB driver class name cannot be null!");
21 }
22
23 if (maxConnections < 0) {
24 throw new SQLException(
25 "DBPool '" + dbURL + "' could not be created: " +
26 "Max connections must be greater than zero!");
27 }
28
29
30 datasource = new BasicDataSource();
31 datasource.setDriverClassName(dbDriver);
32
33 datasource.setUrl(dbURL);
34 datasource.setUsername(dbUser);
35 datasource.setPassword(dbPassword);
36 datasource.setMaxActive(maxConnections);
37 datasource.setMinIdle(1);
38 datasource.setMaxWait(maxIdleSeconds);
39 datasource.setMaxOpenPreparedStatements(maxStatementsPerConnection);
40
41 if (dbValidationQuery != null) {
42 datasource.setValidationQuery(dbValidationQuery);
43 if(!validateOnCheckout)
44 datasource.setTestOnBorrow(true);
45 else
46 datasource.setTestOnReturn(true);
47 datasource.setTimeBetweenEvictionRunsMillis(idleValidationSeconds);
48 }
49 }
View Code