详解 Spring 配置数据源的两种方式
在 Spring 框架中配置数据源(DataSource)主要有两种方式:
- 通过 Setter 注入配置数据源
- 通过 jdbc.properties 配置文件方式
本博文将使用 Druid 作为数据源,其在 Spring 项目中常见且高效。
Druid 被广泛认为是性能最佳的连接池之一,尤其在高并发场景下表现优异。它支持快速的连接获取和释放,优化了资源管理
🌱 1. 通过 Setter 注入配置 Druid 数据源
✅ 1.1 Maven 依赖
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.2.24</version> <!-- 请根据项目需要选择版本 -->
</dependency>
✅ 1.2 XML 配置
修改 applicationContext.xml
文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- Druid 数据源配置 -->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" destroy-method="close">
<property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/mydb"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
<!-- Druid 特有属性 -->
<property name="initialSize" value="5"/>
<property name="minIdle" value="5"/>
<property name="maxActive" value="20"/>
<property name="maxWait" value="60000"/>
<property name="timeBetweenEvictionRunsMillis" value="60000"/>
<property name="minEvictableIdleTimeMillis" value="300000"/>
<property name="validationQuery" value="SELECT 1"/>
<property name="testWhileIdle" value="true"/>
<property name="testOnBorrow" value="false"/>
<property name="testOnReturn" value="false"/>
</bean>
<!-- JdbcTemplate 配置 -->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"/>
</bean>
</beans>
✅ 1.3 Java Config 配置 (推荐方式)
import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.core.JdbcTemplate;
import javax.sql.DataSource;
@Configuration
public class DataSourceConfig {
@Bean(destroyMethod = "close") // 指定关闭方法,释放资源
public DataSource dataSource() {
DruidDataSource dataSource = new DruidDataSource();
dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
dataSource.setUrl("jdbc:mysql://localhost:3306/mydb");
dataSource.setUsername("root");
dataSource.setPassword("root");
// Druid 特有属性
dataSource.setInitialSize(5);
dataSource.setMinIdle(5);
dataSource.setMaxActive(20);
dataSource.setMaxWait(60000);
dataSource.setTimeBetweenEvictionRunsMillis(60000);
dataSource.setMinEvictableIdleTimeMillis(300000);
dataSource.setValidationQuery("SELECT 1");
dataSource.setTestWhileIdle(true);
dataSource.setTestOnBorrow(false);
dataSource.setTestOnReturn(false);
return dataSource;
}
@Bean
public JdbcTemplate jdbcTemplate(DataSource dataSource) {
return new JdbcTemplate(dataSource);
}
}
🗂️ 2. 通过 jdbc.properties 文件配置 Druid 数据源(推荐用于生产环境)
✅ 2.1 jdbc.properties 文件
# MySQL数据库配置
jdbc.driver=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/mydb
jdbc.username=root
jdbc.password=root
✅ 2.2 XML 配置
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation=
"http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
">
<!--1.开启命名空间-->
<!--2.使用 context 空间加载 properties 文件-->
<!-- <context:property-placeholder location="jdbc.properties" system-properties-mode="NEVER"/>
<context:property-placeholder location="jdbc.properties,jdbc2.properties" system-properties-mode="NEVER"/>
<context:property-placeholder location="*.properties" system-properties-mode="NEVER"/>
<context:property-placeholder location="classpath:*.properties" system-properties-mode="NEVER"/> -->
<!--加载最全的方式,除了本项目路径下的 properties,还可以加载 jar 包下的properties -->
<context:property-placeholder location="classpath*:*.properties" system-properties-mode="NEVER"/>
<!--3.使用属性占位符 ${} 加载 properties 文件内容-->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</bean>
<bean id="userDao" class="com.alivinfer.dao.impl.UserDaoImpl">
<property name="name" value="${jdbc.driver}"/>
</bean>
</beans>
💡 注意:
使用property-placeholder
标签需要引入以下命名空间:
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd"
✅ 2.3 Java Config 配置 (推荐方式)
import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.env.Environment;
import org.springframework.jdbc.core.JdbcTemplate;
import javax.annotation.Resource;
import javax.sql.DataSource;
@Configuration
@PropertySource("classpath:jdbc.properties") // 引入 properties 文件
public class DataSourceConfig {
@Resource
private Environment env;
@Bean(destroyMethod = "close")
public DataSource dataSource() {
DruidDataSource dataSource = new DruidDataSource();
dataSource.setDriverClassName(env.getProperty("jdbc.driver"));
dataSource.setUrl(env.getProperty("jdbc.url"));
dataSource.setUsername(env.getProperty("jdbc.username"));
dataSource.setPassword(env.getProperty("jdbc.password"));
dataSource.setInitialSize(Integer.parseInt(env.getProperty("druid.initialSize")));
dataSource.setMinIdle(Integer.parseInt(env.getProperty("druid.minIdle")));
dataSource.setMaxActive(Integer.parseInt(env.getProperty("druid.maxActive")));
dataSource.setMaxWait(Long.parseLong(env.getProperty("druid.maxWait")));
dataSource.setTimeBetweenEvictionRunsMillis(Long.parseLong(env.getProperty("druid.timeBetweenEvictionRunsMillis")));
dataSource.setMinEvictableIdleTimeMillis(Long.parseLong(env.getProperty("druid.minEvictableIdleTimeMillis")));
dataSource.setValidationQuery(env.getProperty("druid.validationQuery"));
dataSource.setTestWhileIdle(Boolean.parseBoolean(env.getProperty("druid.testWhileIdle")));
dataSource.setTestOnBorrow(Boolean.parseBoolean(env.getProperty("druid.testOnBorrow")));
dataSource.setTestOnReturn(Boolean.parseBoolean(env.getProperty("druid.testOnReturn")));
return dataSource;
}
@Bean
public JdbcTemplate jdbcTemplate(DataSource dataSource) {
return new JdbcTemplate(dataSource);
}
}
✅ 测试代码
package com.alivinfer;
import org.junit.jupiter.api.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import javax.sql.DataSource;
public class SpringTest {
/**
* 测试 xml 配置 druid 数据源
*/
@Test
public void test() {
// 获取 IoC 容器
ApplicationContext applicationContext = new
ClassPathXmlApplicationContext("applicationContext.xml");
// 测试 druid 数据源
DataSource dataSource = (DataSource) applicationContext.getBean("dataSource");
System.out.println(dataSource);
}
}
🕶️ Druid 数据源优势
✅ 高效:相比 DriverManagerDataSource
,Druid 提供更高的并发性能和更好的连接池管理
✅ 稳定:支持 SQL 监控、慢 SQL 记录、防 SQL 注入、异常日志跟踪等特性
✅ 易用:通过配置文件实现灵活的参数调整,方便不同环境下的使用
💡 常见问题
-
Druid 日志过多:
- 在
jdbc.properties
中添加以下配置可减少不必要的日志:
druid.logAbandoned=false druid.removeAbandoned=false
- 在
-
com.mysql.cj.jdbc.Driver 找不到:
- 确保
mysql-connector-java
版本兼容,并检查URL
是否包含serverTimezone
参数:
jdbc.url=jdbc:mysql://localhost:3306/mydb?serverTimezone=UTC
- 确保
-
数据库连接泄漏:
- 启用
removeAbandoned
功能,自动关闭超时未关闭的连接:
druid.removeAbandoned=true druid.removeAbandonedTimeout=1800
- 启用
📌 总结
配置方式 | 优点 | 缺点 | 推荐使用场景 |
---|---|---|---|
Setter 注入 (XML/Java Config) | 简单直观,便于理解 | 配置写在代码中,生产环境不推荐 | 小型项目、快速开发、临时测试 |
jdbc.properties 文件 (XML/Java Config) | 配置与代码解耦、支持环境切换、易于维护 | 需要维护额外的配置文件,但在中大型项目中是必要的 | 企业级项目、生产环境、灵活配置 |
推荐使用:
- 在 企业项目 和 生产环境 中,推荐使用 jdbc.properties 文件方式结合 Java Config,确保代码简洁、配置灵活,充分利用 Druid 的性能优势和监控功能