ServiceLoader通过扫描META-INF/services/java.sql.Driver文件自动加载数据库驱动,要求接口为java.sql.Driver、路径严格匹配、每行仅一个无空格类名;DriverManager在静态块中调用ServiceLoader.load(Driver.class)初始化并依次验证acceptsURL,首个返回true的驱动生效,异常默认静默需手动调试验证。

ServiceLoader如何自动发现数据库驱动
Java程序连接数据库时,不需要手动调用Class.forName()或new Driver(),靠的就是ServiceLoader在后台自动扫描并加载驱动。它会读取每个JAR包中META-INF/services/java.sql.Driver文件,逐行解析其中的全限定类名(如com.mysql.cj.jdbc.Driver),然后尝试加载、实例化,并注册到DriverManager。
关键配置必须严格合规
驱动JAR要被正确识别,以下三点缺一不可:
- 接口必须是标准的
java.sql.Driver,不能是子类或自定义接口 - 配置文件路径必须为
META-INF/services/java.sql.Driver(大小写敏感,不能多空格、BOM或注释) - 每行只写一个驱动类全名,末尾不能有空白字符
DriverManager内部依赖ServiceLoader完成初始化
DriverManager在静态块中调用loadInitialDrivers(),该方法直接使用ServiceLoader.load(Driver.class)获取所有可用驱动。之后每个驱动的acceptsURL("jdbc:mysql://...")会被依次调用——只有返回true的那个驱动才会真正参与连接建立。这意味着:
- MySQL 5.x(
com.mysql.jdbc.Driver)不支持jdbc:mysql:aurora:// - MySQL 8.x(
com.mysql.cj.jdbc.Driver)才支持新协议和默认SSL行为 - 若同时引入两个版本驱动,
ServiceLoader会全部加载,但最终生效的是第一个acceptsURL返回true的
异常容易被静默吞掉,调试需主动干预
ServiceLoader默认遇到类加载失败、ServiceConfigurationError等异常不会抛出,而是跳过该实现继续遍历。这导致驱动“没加载成功”却无报错。定位问题可:
- 在
DriverManager.getConnection()前打断点,查看DriverManager.registeredDrivers列表内容 - 手动遍历
ServiceLoader.load(Driver.class),对每个driver调用driver.acceptsURL(url)验证匹配性 - 检查模块系统项目是否在
module-info.java中声明uses java.sql.Driver;










