火柴人战争4无敌MOD
68.98MB · 2025-11-12
MyBatis-Plus(简称MP)是MyBatis的增强工具,以无侵入性为核心设计理念,在MyBatis基础上仅做功能扩展而不修改原生逻辑。通过内置通用CRUD、代码生成器等模块,MP将单表操作效率提升至极致。
MP的整体架构主要包含以下几层:
BaseMapper是MP提供的核心接口,通过动态代理机制实现SQL自动生成。源码核心在于MapperProxy类的实现:
// MapperProxy核心实现逻辑
public class MapperProxy<T> implements InvocationHandler, Serializable {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 处理Object类方法
if (Object.class.equals(method.getDeclaringClass())) {
return method.invoke(this, args);
}
// 处理接口默认方法
if (method.isDefault()) {
return invokeDefaultMethod(proxy, method, args);
}
// 创建MapperMethod并执行
final MapperMethod mapperMethod = cachedMapperMethod(method);
return mapperMethod.execute(sqlSession, args);
}
// 缓存MapperMethod对象
private MapperMethod cachedMapperMethod(Method method) {
return methodCache.computeIfAbsent(method, k -> new MapperMethod(mapperInterface, method, sqlSession.getConfiguration()));
}
}
MP通过MybatisMapperAnnotationBuilder在初始化时,将BaseMapper的通用方法注入到MyBatis的Configuration中:
// SQL注入核心实现
public class DefaultSqlInjector extends AbstractSqlInjector {
@Override
public List<AbstractMethod> getMethodList(Class<?> mapperClass) {
return Stream.of(
new Insert(),
new Delete(),
new Update(),
new SelectById(),
new SelectBatchByIds(),
new SelectByMap(),
new SelectOne(),
new SelectCount(),
new SelectList()
// 更多方法...
).collect(toList());
}
}
Wrapper是MP提供的强大条件构造API,其核心实现在AbstractWrapper类中:
// AbstractWrapper核心方法
protected <V> Children doIt(String column, V val, SqlKeyword sqlKeyword, String... append) {
return columnToString(column, val, sqlKeyword, append);
}
protected <V> Children columnToString(String column, V val, SqlKeyword sqlKeyword, String... append) {
return addCondition(columnToString(column, sqlKeyword, val), val);
}
LambdaWrapper通过Lambda表达式获取属性名,避免硬编码:
// Lambda表达式处理
public static <T> String getColumn(LambdaExpression<T, ?> lambdaExpression) {
// 解析Lambda表达式获取属性名
SerializedLambda serializedLambda = getSerializedLambda(lambdaExpression);
String implMethodName = serializedLambda.getImplMethodName();
// 从方法名提取字段名,如getUserName -> user_name
String fieldName = StringUtils.resolveFieldName(implMethodName);
return fieldName;
}
分页插件是MP最常用的插件之一,核心实现在PaginationInnerInterceptor类:
// 分页插件核心逻辑
@Override
public Object intercept(Invocation invocation) throws Throwable {
// 获取原始SQL
StatementHandler statementHandler = PluginUtils.realTarget(invocation.getTarget());
MetaObject metaObject = SystemMetaObject.forObject(statementHandler);
// 解析分页参数
processPage(metaObject, invocation);
// 执行原始SQL
return invocation.proceed();
}
// 处理分页逻辑
protected void processPage(MetaObject metaObject, Invocation invocation) {
// 获取Page对象
Page<?> page = getPage(metaObject);
if (page == null) {
return;
}
// 重写SQL为分页查询
String originalSql = (String) metaObject.getValue(BOUND_SQL_SQL);
String pageSql = dialect.buildPaginationSql(originalSql, page.offset(), page.getSize());
metaObject.setValue(BOUND_SQL_SQL, pageSql);
// 处理总数查询
countTotal(invocation, metaObject, page, originalSql);
}
OptimisticLockerInnerInterceptor实现乐观锁机制,通过版本号控制并发:
// 乐观锁核心逻辑
@Override
protected void processUpdate(InnerInterceptor.InnerInterceptorChain chain, MetaObject metaObject, String sql, Object parameterObject, Object target, int index) {
// 检查是否需要处理乐观锁
if (!(parameterObject instanceof MapperMethod.ParamMap)) {
return;
}
// 获取版本号字段信息
TableInfo tableInfo = TableInfoHelper.getTableInfo(target.getClass());
if (tableInfo == null || tableInfo.getVersionFieldInfo() == null) {
return;
}
// 处理版本号递增和条件设置
FieldInfo versionField = tableInfo.getVersionFieldInfo();
Object originalVersion = versionField.get(target);
// 版本号加1
Object newVersion = getNewVersion(originalVersion, versionField);
// 设置新的版本号
versionField.set(target, newVersion);
// 添加版本号条件
((MapperMethod.ParamMap<?>) parameterObject).put(VERSION_ORIGINAL, originalVersion);
}
TenantLineInnerInterceptor实现多租户数据隔离:
// 多租户插件核心逻辑
@Override
protected void processSelect(InnerInterceptor.InnerInterceptorChain chain, MetaObject metaObject, String sql, Object parameterObject, BoundSql boundSql) {
// 获取租户处理器
TenantLineHandler tenantLineHandler = getTenantLineHandler();
if (!tenantLineHandler.ignoreTable(getTableName(sql))) {
// 重写SQL,添加租户ID条件
String newSql = tenantLineHandler.buildSql(sql, getTableName(sql));
metaObject.setValue(BOUND_SQL_SQL, newSql);
}
}
MP与Spring Boot集成的核心在于MybatisPlusAutoConfiguration类:
// MP自动配置类
@Configuration
@ConditionalOnClass({SqlSessionFactory.class, SqlSessionFactoryBean.class})
@ConditionalOnSingleCandidate(DataSource.class)
@EnableConfigurationProperties(MybatisPlusProperties.class)
public class MybatisPlusAutoConfiguration {
@Bean
@ConditionalOnMissingBean
public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception {
// 使用MyBatis-Plus的SqlSessionFactoryBean
MybatisSqlSessionFactoryBean factory = new MybatisSqlSessionFactoryBean();
factory.setDataSource(dataSource);
factory.setVfs(SpringBootVFS.class);
// 配置MyBatis-Plus特定组件
factory.setGlobalConfig(globalConfig);
factory.setPlugins(plugins);
factory.setTypeHandlers(typeHandlers);
// 注入SQL注入器
if (globalConfig.getSqlInjector() != null) {
factory.setSqlInjector(globalConfig.getSqlInjector());
}
return factory.getObject();
}
}
在启动过程中,MP会执行以下关键步骤:
MP的IService接口提供了高效的批量操作方法,核心实现在ServiceImpl类:
// 批量保存实现
@Transactional(rollbackFor = Exception.class)
@Override
public boolean saveBatch(Collection<T> entityList, int batchSize) {
String sqlStatement = getSqlStatement(SqlMethod.INSERT_ONE);
return executeBatch(entityList, batchSize, (sqlSession, entity) -> sqlSession.insert(sqlStatement, entity));
}
// 批量执行核心方法
protected <E> boolean executeBatch(Collection<E> list, int batchSize, BiConsumer<SqlSession, E> consumer) {
return SqlHelper.executeBatch(this.entityClass, this.log, list, batchSize, consumer);
}
MP的代码生成器通过模板引擎和数据库元数据读取实现快速代码生成:
// 代码生成器核心逻辑
public AutoGenerator execute() {
// 初始化配置
initEntityNameConvert();
// 生成各层代码
if (null != config.getStrategyConfig().getSuperEntityClass()) {
generateByTable(config);
} else {
generateByPackage(config);
}
return this;
}
// 按表生成代码
protected void generateByTable(ConfigBuilder config) {
// 读取表元数据
List<TableInfo> tableList = config.getTableInfoList();
for (TableInfo tableInfo : tableList) {
// 生成实体类
if (null != tableInfo && StringUtils.isNotBlank(tableInfo.getEntityName())) {
generateEntity(tableInfo);
generateMapper(tableInfo);
generateXml(tableInfo);
generateService(tableInfo);
generateController(tableInfo);
}
}
}
MetaObjectHandler实现字段自动填充:
// 自动填充核心方法
@Override
public void insertFill(MetaObject metaObject) {
// 设置创建时间
this.strictInsertFill(metaObject, "createTime", LocalDateTime.class, LocalDateTime.now());
// 设置更新时间
this.strictInsertFill(metaObject, "updateTime", LocalDateTime.class, LocalDateTime.now());
}
@Override
public void updateFill(MetaObject metaObject) {
// 设置更新时间
this.strictUpdateFill(metaObject, "updateTime", LocalDateTime.class, LocalDateTime.now());
}
通过TableNameHandler实现动态表名:
// 动态表名处理器示例
public class DynamicTableNameHandler implements TableNameHandler {
@Override
public String dynamicTableName(String sql, String tableName) {
// 从ThreadLocal获取表名后缀
String suffix = TableNameContextHolder.getSuffix();
if (StringUtils.isNotBlank(suffix)) {
return tableName + "_" + suffix;
}
return tableName;
}
}
MP通过扩展MyBatis的核心组件实现功能增强,主要集成点包括:
MybatisSqlSessionFactoryBean继承并增强原生实现ISqlInjector接口注入通用CRUD方法ParameterHandler处理特殊参数MP内置多种性能优化机制:
MyBatis-Plus通过巧妙的设计,在不破坏MyBatis原有功能的基础上,提供了丰富的增强特性。其核心优势在于:
通过深入理解MyBatis-Plus的源码实现,开发者可以更好地利用其功能,并在需要时进行定制化扩展。