提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
文章目录
前言
代码预警-内存泄漏
一、两份代码
重点在 public DataSource routingDataSource() 这个方法
会导致连接池多份配置:
java
package com.atguigu.llmcallback.Configuration;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import javax.sql.DataSource;
import java.util.HashMap;
import java.util.Map;
@Configuration
@EnableTransactionManagement
public class DataSourceConfig {
@Bean
@ConfigurationProperties(prefix = "spring.datasource")
public DataSource masterDataSource() {
return DataSourceBuilder.create().build();
}
@Bean
@ConfigurationProperties(prefix = "spring.datasource.slave")
public DataSource slaveDataSource() {
return DataSourceBuilder.create().build();
}
@Primary
@Bean
public DataSource routingDataSource() {
RoutingDataSource routing = new RoutingDataSource();
Map<Object, Object> dsMap = new HashMap<>();
dsMap.put("master", masterDataSource());
dsMap.put("slave", slaveDataSource());
routing.setDefaultTargetDataSource(masterDataSource());
routing.setTargetDataSources(dsMap);
return routing;
}
@Bean
public JdbcTemplate jdbcTemplate(DataSource routingDataSource) {
return new JdbcTemplate(routingDataSource);
}
@Bean
public PlatformTransactionManager transactionManager(DataSource routingDataSource) {
return new DataSourceTransactionManager(routingDataSource);
}
}
修改后:
java
package com.atguigu.llmcallback.Configuration;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import javax.sql.DataSource;
import java.util.HashMap;
import java.util.Map;
@Configuration
@EnableTransactionManagement
public class DataSourceConfig {
@Bean
@ConfigurationProperties(prefix = "spring.datasource")
public DataSource masterDataSource() {
return DataSourceBuilder.create().build();
}
@Bean
@ConfigurationProperties(prefix = "spring.datasource.slave")
public DataSource slaveDataSource() {
return DataSourceBuilder.create().build();
}
/**
* ✅ 路由数据源(核心)
*/
@Primary
@Bean
public DataSource routingDataSource(
DataSource masterDataSource,
DataSource slaveDataSource) {
RoutingDataSource routing = new RoutingDataSource();
Map<Object, Object> dsMap = new HashMap<>();
dsMap.put("master", masterDataSource);
dsMap.put("slave", slaveDataSource);
routing.setDefaultTargetDataSource(masterDataSource);
routing.setTargetDataSources(dsMap);
return routing;
}
@Bean
public JdbcTemplate jdbcTemplate(DataSource routingDataSource) {
return new JdbcTemplate(routingDataSource);
}
@Bean
public PlatformTransactionManager transactionManager(DataSource routingDataSource) {
return new DataSourceTransactionManager(routingDataSource);
}
}
二、原因
原来通过静态调用相当于直接new了一份,所以连接池会有多份一样的配置。
java
@Bean
public DataSource routingDataSource() {
DataSource master = masterDataSource(); // 普通方法调用
DataSource slave = slaveDataSource(); // 普通方法调用
...
}
java
routingDataSource() {
DataSource master = new HikariDataSource(...); // new 了一个新的
DataSource slave = new HikariDataSource(...); // 又 new 了一个新的
}
Configuration注解会自动拦截配置参数,并在已有Bean实例中获取,所以可以保证单例。
总结
AI代码审查还是挺有用的