Tomcat如何加载JDBC数据源二

104 阅读1分钟

在上一篇中讲到了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查看注册后的信息。如下图所示:

image.png

最后在/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>