在上一篇中讲到了Tomcat如何配置JDBC数据源,那么这一篇我们从源码开始分析,Tomcat是如何加载JDBC数据源,并提供给我们使用的。
Tomcat通过JNDI的方式配置数据源。那么我们下面就开始跟踪源码一起看看Tomcat是如何加载JDBC数据源的吧。
首先tomcat启动会执行LifecycleBase#start()
public final synchronized void start() throws LifecycleException {
if (state.equals(LifecycleState.NEW)) {
//初始化各个模块
init();
} else if (state.equals(LifecycleState.FAILED)){
stop();
} else if (!state.equals(LifecycleState.INITIALIZED) &&
!state.equals(LifecycleState.STOPPED)) {
invalidTransition(Lifecycle.BEFORE_START_EVENT);
}
setStateInternal(LifecycleState.STARTING_PREP, null, false);
//启动各个模块
startInternal();
从上面的代码可以看到,启动前会先执行初始化操作。JNDI相关的实现类是 NamingResourcesImpl。init方法会调用NamingResourcesImpl#initInternal()。
protected void initInternal() throws LifecycleException {
super.initInternal();
// 在我们注册当前已知的命名资源之前设置它以避免时间问题。 重复注册不是问题。
resourceRequireExplicitRegistration = true;
//加载context.xml中配置的Resource。并为此注册一个 MBean
for (ContextResource cr : resources.values()) {
try {
MBeanUtils.createMBean(cr);
} catch (Exception e) {
log.warn(sm.getString(
"namingResources.mbeanCreateFail", cr.getName()), e);
}
}
}
在context.xml配置的以下Resource,将在初始化阶段被获取并注册MBean
<Resource name="jdbc/TestDB"
auth="Container"
type="javax.sql.DataSource"
username="dbusername"
password="dbpassword"
driverClassName="com.mysql.cj.jdbc.Driver"
url="jdbc:mysql://mysqlUrl:mysqlPort/databaseName"
maxTotal="8"
maxIdle="4"/>
注册完成可以打开jconsole查看注册后的信息。如下图所示:
最后在/WEB-INF/web.xml
来引用/定义资源。
<resource-ref>
<description>对 java.sql.Connection 实例的工厂的资源引用,可用于与 Web 应用程序的 <Context> 配置中配置的特定数据库进行通信。
</description>
<res-ref-name>
jdbc/TestDB
</res-ref-name>
<res-type>
javax.sql.DataSource
</res-type>
<res-auth>
Container
</res-auth>
</resource-ref>