public void init() throws SQLException {
    if (inited) {
        // 如果已经被初始化过,则终止该方法
        return;
    }

    // bug fixed for dead lock, for issue #2980
    DruidDriver.getInstance();

    // 获取重入锁
    final ReentrantLock lock = this.lock;
    try {
        lock.lockInterruptibly();
    } catch (InterruptedException e) {
        throw new SQLException("interrupt", e);
    }

    boolean init = false;
    try {
        // 双重检查
        if (inited) {
            return;
        }

        initStackTrace = Utils.toString(Thread.currentThread().getStackTrace());

        // 生成连接池 id
        this.id = DruidDriver.createDataSourceId();
        if (this.id > 1) {
            // 生成其他对象的 id,比如连接对象的 id、statement 对象的 id
            long delta = (this.id - 1) * 100000;
            this.connectionIdSeedUpdater.addAndGet(this, delta);
            this.statementIdSeedUpdater.addAndGet(this, delta);
            this.resultSetIdSeedUpdater.addAndGet(this, delta);
            this.transactionIdSeedUpdater.addAndGet(this, delta);
        }

        if (this.jdbcUrl != null) {
            this.jdbcUrl = this.jdbcUrl.trim();
            // jdbc url 的头必须是 jdbc:wrap-jdbc 才会触发该方法里的逻辑(这个头貌似是 oracle 的?本篇文章仅针对 mysql)
            initFromWrapDriverUrl();
        }

        for (Filter filter : filters) {
            // 通过池对象初始化 filters(因为 filter 里面可能会用到一些池属性)
            filter.init(this);
        }

        if (this.dbTypeName == null || this.dbTypeName.length() == 0) {
            // 根据 jdbc 协议头分析出当前数据库的类型(本文默认 mysql)
            this.dbTypeName = JdbcUtils.getDbType(jdbcUrl, null);
        }

        DbType dbType = DbType.of(this.dbTypeName);
        if (dbType == DbType.mysql
                || dbType == DbType.mariadb
                || dbType == DbType.oceanbase
                || dbType == DbType.ads) {
            boolean cacheServerConfigurationSet = false;
            if (this.connectProperties.containsKey("cacheServerConfiguration")) {
                cacheServerConfigurationSet = true;
            } else if (this.jdbcUrl.indexOf("cacheServerConfiguration") != -1) {
                cacheServerConfigurationSet = true;
            }
            if (cacheServerConfigurationSet) {
                this.connectProperties.put("cacheServerConfiguration", "true");
            }
        }

        // 下面就是对设置的这些属性合理性的判断,不符合要求的将直接抛异常
        if (maxActive <= 0) {
            throw new IllegalArgumentException("illegal maxActive " + maxActive);
        }

        if (maxActive < minIdle) {
            throw new IllegalArgumentException("illegal maxActive " + maxActive);
        }

        if (getInitialSize() > maxActive) {
            throw new IllegalArgumentException("illegal initialSize " + this.initialSize + ", maxActive " + maxActive);
        }

        if (timeBetweenLogStatsMillis > 0 && useGlobalDataSourceStat) {
            throw new IllegalArgumentException("timeBetweenLogStatsMillis not support useGlobalDataSourceStat=true");
        }

        if (maxEvictableIdleTimeMillis < minEvictableIdleTimeMillis) {
            throw new SQLException("maxEvictableIdleTimeMillis must be grater than minEvictableIdleTimeMillis");
        }

        if (keepAlive && keepAliveBetweenTimeMillis <= timeBetweenEvictionRunsMillis) {
            throw new SQLException("keepAliveBetweenTimeMillis must be grater than timeBetweenEvictionRunsMillis");
        }

        if (this.driverClass != null) {
            this.driverClass = driverClass.trim();
        }

        // 通过 SPI 机制加载责任链上需要执行的 filter,方法详情在下面
        initFromSPIServiceLoader();

        // 如果 driver 为空,加载驱动,最终将加载到的驱动注册到 DriverManager 上去
        resolveDriver();

        // 根据 dbType 的不同,来初始化一些标记字段(比如 isMySql)
        initCheck();

        // 异常处理器初始化
        initExceptionSorter();
        // 初始化长连接检测时所需要用到的 checker 的适配类型,具体实现在下面
        initValidConnectionChecker();
        // 简单的检测 validationQuery 参数是否填写了,若没填写会打印一个错误日志,不影响主流程
        validationQueryCheck();

        // 默认不开启,忽略
        if (isUseGlobalDataSourceStat()) {
            dataSourceStat = JdbcDataSourceStat.getGlobal();
            if (dataSourceStat == null) {
                dataSourceStat = new JdbcDataSourceStat("Global", "Global", this.dbTypeName);
                JdbcDataSourceStat.setGlobal(dataSourceStat);
            }
            if (dataSourceStat.getDbType() == null) {
                dataSourceStat.setDbType(this.dbTypeName);
            }
        } else {
            dataSourceStat = new JdbcDataSourceStat(this.name, this.jdbcUrl, this.dbTypeName, this.connectProperties);
        }
        dataSourceStat.setResetStatEnable(this.resetStatEnable);

        // 下面三个数组都跟池子本身有关系,所以容量为 maxActive
        // 初始化连接池本体
        connections = new DruidConnectionHolder[maxActive];
        // 初始化丢弃连接数组(流程 4.1 需要用到)
        evictConnections = new DruidConnectionHolder[maxActive];
        // 初始化需要检测可用性连接数组(保活检测)(流程4.1要用)
        keepAliveConnections = new DruidConnectionHolder[maxActive];

        SQLException connectError = null;

        // 另外一种通过线程池管理连接池的方式,默认不启用,忽略
        if (createScheduler != null && asyncInit) {
            for (int i = 0; i < initialSize; ++i) {
                submitCreateTask(true);
            }
        } else if (!asyncInit) {
            // init connections
            //当池子里的连接数少于需要初始化的个数时,则需要不断新增连接填充连接池,直到等于初始化连接数
            while (poolingCount < initialSize) {
                try {
                    // 直接通过驱动程序创建连接对象,参考流程 2.1
                    PhysicalConnectionInfo pyConnectInfo = createPhysicalConnection();
                    // 拿着驱动连接包装成 holder 对象
                    DruidConnectionHolder holder = new DruidConnectionHolder(this, pyConnectInfo);
                    // 生成好的连接直接往后排
                    connections[poolingCount++] = holder;
                } catch (SQLException ex) {
                    LOG.error("init datasource error, url: " + this.getUrl(), ex);
                    if (initExceptionThrow) {
                        connectError = ex;
                        break;
                    } else {
                        // 异常报错后会休眠 3s 来进行下次的添加
                        Thread.sleep(3000);
                    }
                }
            }

            if (poolingCount > 0) {
                poolingPeak = poolingCount;
                poolingPeakTime = System.currentTimeMillis();
            }
        }

        // 开启打印 log 日志的守护线程
        createAndLogThread();
        // 开启负责新增连接的守护线程(主流程3)
        createAndStartCreatorThread();
        // 开启负责丢弃连接的守护线程(主流程4)
        createAndStartDestroyThread();

        //倒计数器,用来保证上面的主流程 3 和 4 两个守护线程全部开启完毕后才进行接下来的操作
        initedLatch.await();
        init = true;

        initedTime = new Date();
        registerMbean();

        if (connectError != null && poolingCount == 0) {
            throw connectError;
        }

        if (keepAlive) {
            // async fill to minIdle
            // 默认不启用该模式,忽略
            if (createScheduler != null) {
                for (int i = 0; i < minIdle; ++i) {
                    submitCreateTask(true);
                }
            } else {
                // keepAlive=true,主动唤起主流程 3 一次
                this.emptySignal();
            }
        }

    } catch (SQLException e) {
        LOG.error("{dataSource-" + this.getID() + "} init error", e);
        throw e;
    } catch (InterruptedException e) {
        throw new SQLException(e.getMessage(), e);
    } catch (RuntimeException e){
        LOG.error("{dataSource-" + this.getID() + "} init error", e);
        throw e;
    } catch (Error e){
        LOG.error("{dataSource-" + this.getID() + "} init error", e);
        throw e;

    } finally {
        // 初始化完成后置为 true
        inited = true;
        // 释放锁
        lock.unlock();

        if (init && LOG.isInfoEnabled()) {
            String msg = "{dataSource-" + this.getID();

            if (this.name != null && !this.name.isEmpty()) {
                msg += ",";
                msg += this.name;
            }

            msg += "} inited";

            LOG.info(msg);
        }
    }
}

// 如果 driver 为空,加载驱动,最终将加载到的驱动注册到 DriverManager 上去
protected void resolveDriver() throws SQLException {
    if (this.driver == null) {
        if (this.driverClass == null || this.driverClass.isEmpty()) {
            // 在 driverClass 不配置的情况下,druid 会通过 url 来判定属于哪个 driverClass
            this.driverClass = JdbcUtils.getDriverClassName(this.jdbcUrl);
        }

        // 忽略
        if (MockDriver.class.getName().equals(driverClass)) {
            driver = MockDriver.instance;
        } else if ("com.alibaba.druid.support.clickhouse.BalancedClickhouseDriver".equals(driverClass)) {
            Properties info = new Properties();
            info.put("user", username);
            info.put("password", password);
            info.putAll(connectProperties);
            driver = new BalancedClickhouseDriver(jdbcUrl, info);
        } else {
            if (jdbcUrl == null && (driverClass == null || driverClass.length() == 0)) {
                throw new SQLException("url not set");
            }
            // driverClass 不为空的情况下直接触发驱动加载
            driver = JdbcUtils.createDriver(driverClassLoader, driverClass);
        }
    } else {
        // 除非手动设置驱动,否则不会走这里的逻辑
        if (this.driverClass == null) {
            this.driverClass = driver.getClass().getName();
        }
    }
}

private void initFromSPIServiceLoader() {
    // 默认不跳过 SPI 加载
    if (loadSpifilterSkip) {
        return;
    }

    if (autoFilters == null) {
        List<Filter> filters = new ArrayList<Filter>();
        // 加载 Filter 的实现
        ServiceLoader<Filter> autoFilterLoader = ServiceLoader.load(Filter.class);

        for (Filter filter : autoFilterLoader) {
            AutoLoad autoLoad = filter.getClass().getAnnotation(AutoLoad.class);
            if (autoLoad != null && autoLoad.value()) {
                filters.add(filter);
            }
        }
        autoFilters = filters;
    }

    for (Filter filter : autoFilters) {
        if (LOG.isInfoEnabled()) {
            LOG.info("load filter from spi :" + filter.getClass().getName());
        }
        // 把通过 SPI 机制加载到的 filter 放到池子的 filters 里,用于后续责任链触发
        addFilter(filter);
    }
}

// 初始化 checker
private void initValidConnectionChecker() {
    if (this.validConnectionChecker != null) {
        return;
    }

    // 根据驱动的 class 名称,来适配具体的 checker 实现
    String realDriverClassName = driver.getClass().getName();
    if (JdbcUtils.isMySqlDriver(realDriverClassName)) {
        // 假设是 mysql 类型的驱动,那么适配到 mysql 的 checker,MySqlValidConnectionChecker 的构造器参考下面的方法
        this.validConnectionChecker = new MySqlValidConnectionChecker();

    } else if (realDriverClassName.equals(JdbcConstants.ORACLE_DRIVER)
            || realDriverClassName.equals(JdbcConstants.ORACLE_DRIVER2)) {
        this.validConnectionChecker = new OracleValidConnectionChecker();

    } else if (realDriverClassName.equals(JdbcConstants.SQL_SERVER_DRIVER)
               || realDriverClassName.equals(JdbcConstants.SQL_SERVER_DRIVER_SQLJDBC4)
               || realDriverClassName.equals(JdbcConstants.SQL_SERVER_DRIVER_JTDS)) {
        this.validConnectionChecker = new MSSQLValidConnectionChecker();

    } else if (realDriverClassName.equals(JdbcConstants.POSTGRESQL_DRIVER)
            || realDriverClassName.equals(JdbcConstants.ENTERPRISEDB_DRIVER)
            || realDriverClassName.equals(JdbcConstants.POLARDB_DRIVER)) {
        this.validConnectionChecker = new PGValidConnectionChecker();
    }
}

// Mysql 对应的 checker 构造器
public MySqlValidConnectionChecker(){
    try {
        clazz = Utils.loadClass("com.mysql.jdbc.MySQLConnection");
        if (clazz == null) {
            clazz = Utils.loadClass("com.mysql.cj.jdbc.ConnectionImpl");
        }

        if (clazz != null) {
            // 如果驱动程序本身有 ping 方法,则下面的 usePingMethod 设置为 true,后续连接保活测试就会采用 ping.invoke 的方式触发。
            ping = clazz.getMethod("pingInternal", boolean.class, int.class);
        }

        if (ping != null) {
            usePingMethod = true;
        }
    } catch (Exception e) {
        LOG.warn("Cannot resolve com.mysql.jdbc.Connection.ping method.  Will use 'SELECT 1' instead.", e);
    }

    configFromProperties(System.getProperties());
}