ps:迷迷糊糊的,回头再看把
DataSourceFactory
public interface DataSourceFactory {
/**
* 设置属性
* @param props
*/
void setProperties(Properties props);
/**
* 获取数据源
* @return
*/
DataSource getDataSource();
}

ya
unpooled

UnpooledDataSourceFactory
UnpooledDataSource
负责new数据源单例的
pooled
*/
public class PooledDataSourceFactory extends UnpooledDataSourceFactory {
// 构造有池化数据源工厂,并初始化默认 PooledDataSource;无参数
public PooledDataSourceFactory() {
this.dataSource = new PooledDataSource();
}
}
<dataSource type="POOLED">
<property name="driver" value="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://127.0.0.1:3306/blog2026_2_2?useSSL=false&serverTimezone=UTC&allowPublicKeyRetrieval=true"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</dataSource>
private DataSourceFactory dataSourceElement(XNode context) throws Exception {
if (context != null) {
String type = context.getStringAttribute("type");
Properties props = context.getChildrenAsProperties();
DataSourceFactory factory = (DataSourceFactory) resolveClass(type).getDeclaredConstructor().newInstance();
factory.setProperties(props);
return factory;
}
throw new BuilderException("Environment declaration requires a DataSourceFactory.");
}
PooledDataSource
public PooledDataSource() {
dataSource = new UnpooledDataSource();
}

获取连接池
popConnection

public class PoolState {
// 关联的数据源(用于读取配置与统计展示)
protected PooledDataSource dataSource;
// 空闲连接列表
protected final List<PooledConnection> idleConnections = new ArrayList<>();
// 活跃连接列表
protected final List<PooledConnection> activeConnections = new ArrayList<>();


pushConnection

Spring集成mybatis

@Test
public void test3() throws Exception{
// 1.获取配置文件
InputStream in = Resources.getResourceAsStream("mybatis-config.xml");
// 2.加载解析配置文件并获取SqlSessionFactory对象
SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
SqlSessionFactory factory = sqlSessionFactoryBuilder.build(in);
// 3.根据SqlSessionFactory对象获取SqlSession对象
SqlSession sqlSession = factory.openSession(ExecutorType.BATCH, false);
// 4.通过SqlSession中提供的 API方法来操作数据库
List<User> list ;
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
list = mapper.selectUserList();
for (User user : list) {
System.out.println(user.getUserName());
}
// 5.关闭会话
sqlSession.close();
}
谁帮我做了这些
SqlSessionFactory


// 创建SqlSessionFactory
@Override
public void afterPropertiesSet() throws Exception {
notNull(dataSource, "Property 'dataSource' is required");
notNull(sqlSessionFactoryBuilder, "Property 'sqlSessionFactoryBuilder' is required");
state((configuration == null && configLocation == null) || !(configuration != null && configLocation != null),
"Property 'configuration' and 'configLocation' can not specified with together");
this.sqlSessionFactory = buildSqlSessionFactory();
}

老朋友都在
// 创建 SqlSessionFactory(MyBatis 集成 Spring 的核心入口)
protected SqlSessionFactory buildSqlSessionFactory() throws Exception {
final Configuration targetConfiguration; // MyBatis 全局配置对象(核心)
XMLConfigBuilder xmlConfigBuilder = null;
// ============================
// 1)加载 MyBatis Configuration
// ============================
if (this.configuration != null) {
// Spring 已经注入了 Configuration(JavaConfig方式)
targetConfiguration = this.configuration;
// 合并 Spring 传入的 properties
if (targetConfiguration.getVariables() == null) {
targetConfiguration.setVariables(this.configurationProperties);
} else if (this.configurationProperties != null) {
targetConfiguration.getVariables().putAll(this.configurationProperties);
}
} else if (this.configLocation != null) {
// 从 mybatis-config.xml 加载配置(XML方式)
xmlConfigBuilder = new XMLConfigBuilder(
this.configLocation.getInputStream(), null, this.configurationProperties);
targetConfiguration = xmlConfigBuilder.getConfiguration();
} else {
// 未指定配置文件 → 使用默认 Configuration
targetConfiguration = new Configuration();
Optional.ofNullable(this.configurationProperties)
.ifPresent(targetConfiguration::setVariables);
}
// ============================
// 2)注册 MyBatis 扩展组件
// ============================
// ObjectFactory:对象实例化策略(反射创建结果对象)
Optional.ofNullable(this.objectFactory)
.ifPresent(targetConfiguration::setObjectFactory);
// ObjectWrapperFactory:包装对象(MetaObject)
Optional.ofNullable(this.objectWrapperFactory)
.ifPresent(targetConfiguration::setObjectWrapperFactory);
// VFS:资源扫描器(用于扫描 classpath)
Optional.ofNullable(this.vfs)
.ifPresent(targetConfiguration::setVfsImpl);
// ============================
// 3)扫描别名 typeAliasesPackage
// ============================
if (hasLength(this.typeAliasesPackage)) {
// Spring 扫描包下的实体类并注册别名(User -> user)
scanClasses(this.typeAliasesPackage, this.typeAliasesSuperType)
.stream()
.filter(clazz -> !clazz.isAnonymousClass())
.filter(clazz -> !clazz.isInterface())
.forEach(targetConfiguration.getTypeAliasRegistry()::registerAlias);
}
// 手动注册别名
if (!isEmpty(this.typeAliases)) {
Stream.of(this.typeAliases).forEach(typeAlias ->
targetConfiguration.getTypeAliasRegistry().registerAlias(typeAlias)
);
}
// ============================
// 4)注册插件 Interceptor(MyBatis 核心扩展点)
// ============================
if (!isEmpty(this.plugins)) {
// Spring 注入的分页插件、审计插件等在这里加入 MyBatis
Stream.of(this.plugins).forEach(plugin ->
targetConfiguration.addInterceptor(plugin)
);
}
// ============================
// 5)注册 TypeHandler(Java类型 ↔ JDBC类型转换)
// ============================
if (hasLength(this.typeHandlersPackage)) {
// 扫描并注册自定义 TypeHandler
scanClasses(this.typeHandlersPackage, TypeHandler.class)
.stream()
.filter(clazz -> !Modifier.isAbstract(clazz.getModifiers()))
.forEach(targetConfiguration.getTypeHandlerRegistry()::register);
}
if (!isEmpty(this.typeHandlers)) {
// 手动注册 TypeHandler
Stream.of(this.typeHandlers).forEach(typeHandler ->
targetConfiguration.getTypeHandlerRegistry().register(typeHandler)
);
}
// 设置默认 Enum 处理器
targetConfiguration.setDefaultEnumTypeHandler(defaultEnumTypeHandler);
// ============================
// 6)注册 LanguageDriver(动态SQL解析器)
// ============================
if (!isEmpty(this.scriptingLanguageDrivers)) {
Stream.of(this.scriptingLanguageDrivers).forEach(languageDriver ->
targetConfiguration.getLanguageRegistry().register(languageDriver)
);
}
Optional.ofNullable(this.defaultScriptingLanguageDriver)
.ifPresent(targetConfiguration::setDefaultScriptingLanguage);
// ============================
// 7)设置 DatabaseId(适配多数据库方言)
// ============================
if (this.databaseIdProvider != null) {
targetConfiguration.setDatabaseId(
this.databaseIdProvider.getDatabaseId(this.dataSource)
);
}
// ============================
// 8)解析 mybatis-config.xml(如果存在)
// ============================
if (xmlConfigBuilder != null) {
xmlConfigBuilder.parse(); // 解析 settings、mappers、plugins 等
}
// ==========================================================
// 9)最关键:MyBatis 集成 Spring 的核心工作
// 设置 Environment(事务工厂 + DataSource)
// ==========================================================
targetConfiguration.setEnvironment(
new Environment(
this.environment,
// SpringManagedTransactionFactory:让 MyBatis 使用 Spring 事务
this.transactionFactory == null
? new SpringManagedTransactionFactory()
: this.transactionFactory,
// Spring 注入的数据源 DataSource
this.dataSource
)
);
// ============================
// 10)解析 Mapper XML 文件
// ============================
if (this.mapperLocations != null) {
for (Resource mapperLocation : this.mapperLocations) {
// XMLMapperBuilder:解析每一个 mapper.xml
XMLMapperBuilder xmlMapperBuilder =
new XMLMapperBuilder(
mapperLocation.getInputStream(),
targetConfiguration,
mapperLocation.toString(),
targetConfiguration.getSqlFragments()
);
// 注册 SQL 语句到 Configuration:MappedStatement
xmlMapperBuilder.parse();
}
}
// ============================
// 11)最终构建 SqlSessionFactory
// ============================
return this.sqlSessionFactoryBuilder.build(targetConfiguration);
}
1..Spring 控制 JDBC Connection 的事务
new SpringManagedTransactionFactory()
2.DataSource 由 Spring 注入
this.dataSource
MyBatis 不再自己创建连接池 而是复用 Spring 管理的:
-
HikariCP
-
Druid
-
C3P0
3.Mapper XML 与 Mapper 接口注册进 Spring
XMLMapperBuilder.parse();
mapper.xml → MappedStatement
Mapper 接口 → Spring Bean
最终实现:
userMapper.selectById()
背后其实是:
SqlSessionTemplate.execute(...)
SqlSession
存在数据安全问题
private SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit) {
Transaction tx = null;
try {
final Environment environment = configuration.getEnvironment();
// 获取事务工厂
final TransactionFactory transactionFactory = getTransactionFactoryFromEnvironment(environment);
// 创建事务
tx = transactionFactory.newTransaction(environment.getDataSource(), level, autoCommit);
// 根据事务工厂和默认的执行器类型,创建执行器 >>
final Executor executor = configuration.newExecutor(tx, execType);
return new DefaultSqlSession(configuration, executor, autoCommit);
} catch (Exception e) {
closeTransaction(tx); // may have fetched a connection so lets call close()
throw ExceptionFactory.wrapException("Error opening session. Cause: " + e, e);
} finally {
ErrorContext.instance().reset();
}
}
SqlSessionTemplate
@Override
public <K, V> Map<K, V> selectMap(String statement, String mapKey) {
return this.sqlSessionProxy.selectMap(statement, mapKey);
}
private final SqlSession sqlSessionProxy;
代理对象
this.sqlSessionProxy = (SqlSession) newProxyInstance(SqlSessionFactory.class.getClassLoader(),
new Class[] { SqlSession.class }, new SqlSessionInterceptor());
finally {
// =====================================================
// 6)finally:确保 SqlSession 正确关闭
// - 如果是事务 SqlSession → 不真正关闭(交给事务管理器)
// - 如果非事务 SqlSession → close 释放连接
// =====================================================
if (sqlSession != null) {
closeSqlSession(sqlSession, SqlSessionTemplate.this.sqlSessionFactory);
}
}
线程安全问题

public abstract class SqlSessionDaoSupport extends DaoSupport {
private SqlSessionTemplate sqlSessionTemplate;
代理mapper

public class MapperScannerConfigurer
implements BeanDefinitionRegistryPostProcessor, InitializingBean, ApplicationContextAware, BeanNameAware {
InitializingBean
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
if (this.processPropertyPlaceHolders) {
processPropertyPlaceHolders();
}
ClassPathMapperScanner scanner = new ClassPathMapperScanner(registry);
scanner.setAddToConfig(this.addToConfig);
scanner.setAnnotationClass(this.annotationClass);
scanner.setMarkerInterface(this.markerInterface);
scanner.setSqlSessionFactory(this.sqlSessionFactory);
scanner.setSqlSessionTemplate(this.sqlSessionTemplate);
scanner.setSqlSessionFactoryBeanName(this.sqlSessionFactoryBeanName);
scanner.setSqlSessionTemplateBeanName(this.sqlSessionTemplateBeanName);
scanner.setResourceLoader(this.applicationContext);
scanner.setBeanNameGenerator(this.nameGenerator);
scanner.setMapperFactoryBeanClass(this.mapperFactoryBeanClass);
if (StringUtils.hasText(lazyInitialization)) {
scanner.setLazyInitialization(Boolean.valueOf(lazyInitialization));
}
if (StringUtils.hasText(defaultScope)) {
scanner.setDefaultScope(defaultScope);
}
scanner.registerFilters();
//扫描注册
scanner.scan(
StringUtils.tokenizeToStringArray(this.basePackage, ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS));
}
