diff --git a/mybatis-flex-solon-plugin/README.md b/mybatis-flex-solon-plugin/README.md
index ee151791..d3e9cfa5 100644
--- a/mybatis-flex-solon-plugin/README.md
+++ b/mybatis-flex-solon-plugin/README.md
@@ -63,19 +63,6 @@ mybatis-flex:
#
```
-主要支持的属性说明:
-
-| 支持属性 | 别名(保持与之前的兼容) | 说明 |
-|-------------------------|----------------------------|----------------------------------|
-| type-aliases-package | typeAliases | 类型别名 |
-| type-aliases-super-type | typeAliasesSuperType | 类型别名的父类(用于过滤) |
-| type-handlers-package | typeHandlers | 类型处理器 |
-| mapper-locations | mappers | mapper 类或xml文件 |
-| configuration | configuration | mybatis 配置。对应类:FlexConfiguration |
-| global-config | globalConfig | 全局部置。对应类:FlexGlobalConfig |
-
-
-
##### Mapper 配置注意事项:
* 通过 mapper 类包名配置。 xml 与 mapper 需同包同名
@@ -95,13 +82,15 @@ mybatis-flex.mapper-locations: "classpath:mybatis/db1/*.xml"
```java
//配置 mf (如果配置不能满足需求,可以进一步代助代码)
-@Configuration
-public class Config {
- @Bean
- public void ormConfig(@Inject FlexConfiguration cfg,
- @Inject FlexGlobalConfig globalConfig) {
+@Component
+public class MyBatisFlexCustomizerImpl implements MyBatisFlexCustomizer, ConfigurationCustomizer {
+ @Override
+ public void customize(FlexGlobalConfig globalConfig) {
- cfg.setCacheEnabled(false);
+ }
+
+ @Override
+ public void customize(FlexConfiguration configuration) {
}
}
diff --git a/mybatis-flex-solon-plugin/src/main/java/com/mybatisflex/core/datasource/FlexDataSourceRouting.java b/mybatis-flex-solon-plugin/src/main/java/com/mybatisflex/core/datasource/FlexDataSourceRouting.java
index 29c32ec3..e149a419 100644
--- a/mybatis-flex-solon-plugin/src/main/java/com/mybatisflex/core/datasource/FlexDataSourceRouting.java
+++ b/mybatis-flex-solon-plugin/src/main/java/com/mybatisflex/core/datasource/FlexDataSourceRouting.java
@@ -5,16 +5,18 @@ import org.noear.solon.data.datasource.RoutingDataSource;
import javax.sql.DataSource;
/**
+ * 数据源路由工具(用于确定当前真实数据源)
+ *
* @author noear 2024/12/3 created
*/
public class FlexDataSourceRouting {
public static DataSource determineCurrentTarget(DataSource original) {
if (original instanceof FlexDataSource) {
- return ((FlexDataSource) original).getDataSource();
+ return determineCurrentTarget(((FlexDataSource) original).getDataSource());
}
if (original instanceof RoutingDataSource) {
- return ((RoutingDataSource) original).determineCurrentTarget();
+ return determineCurrentTarget(((RoutingDataSource) original).determineCurrentTarget());
}
return original;
diff --git a/mybatis-flex-solon-plugin/src/main/java/com/mybatisflex/solon/ConfigurationCustomizer.java b/mybatis-flex-solon-plugin/src/main/java/com/mybatisflex/solon/ConfigurationCustomizer.java
new file mode 100644
index 00000000..9c8d2a5a
--- /dev/null
+++ b/mybatis-flex-solon-plugin/src/main/java/com/mybatisflex/solon/ConfigurationCustomizer.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2022-2025, Mybatis-Flex (fuhai999@gmail.com).
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.mybatisflex.solon;
+
+import com.mybatisflex.core.mybatis.FlexConfiguration;
+
+/**
+ * 为 {@link FlexConfiguration} 做自定义的配置支持。
+ * @author michael
+ */
+@FunctionalInterface
+public interface ConfigurationCustomizer {
+
+ /**
+ * 自定义配置 {@link FlexConfiguration}。
+ *
+ * @param configuration MyBatis Flex Configuration
+ */
+ void customize(FlexConfiguration configuration);
+
+}
diff --git a/mybatis-flex-solon-plugin/src/main/java/com/mybatisflex/solon/MyBatisFlexCustomizer.java b/mybatis-flex-solon-plugin/src/main/java/com/mybatisflex/solon/MyBatisFlexCustomizer.java
new file mode 100644
index 00000000..1237c4a3
--- /dev/null
+++ b/mybatis-flex-solon-plugin/src/main/java/com/mybatisflex/solon/MyBatisFlexCustomizer.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2022-2025, Mybatis-Flex (fuhai999@gmail.com).
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.mybatisflex.solon;
+
+import com.mybatisflex.core.FlexGlobalConfig;
+
+/**
+ *
MyBatis-Flex 配置。
+ *
+ *
一般可以用于去初始化:
+ *
+ *
+ * - FlexGlobalConfig 的全局配置
+ *
- 自定义主键生成器
+ *
- 多租户配置
+ *
- 动态表名配置
+ *
- 逻辑删除处理器配置
+ *
- 自定义脱敏规则
+ *
- SQL 审计配置
+ *
- SQL 打印配置
+ *
- 数据源解密器配置
+ *
- 自定义数据方言配置
+ *
- ...
+ *
+ */
+@FunctionalInterface
+public interface MyBatisFlexCustomizer {
+
+ /**
+ * 自定义 MyBatis-Flex 配置。
+ *
+ * @param globalConfig 全局配置
+ */
+ void customize(FlexGlobalConfig globalConfig);
+}
diff --git a/mybatis-flex-solon-plugin/src/main/java/com/mybatisflex/solon/MybatisFlexAutoConfiguration.java b/mybatis-flex-solon-plugin/src/main/java/com/mybatisflex/solon/MybatisFlexAutoConfiguration.java
new file mode 100644
index 00000000..495fff67
--- /dev/null
+++ b/mybatis-flex-solon-plugin/src/main/java/com/mybatisflex/solon/MybatisFlexAutoConfiguration.java
@@ -0,0 +1,231 @@
+package com.mybatisflex.solon;
+
+import com.mybatisflex.core.FlexConsts;
+import com.mybatisflex.core.FlexGlobalConfig;
+import com.mybatisflex.core.MybatisFlexBootstrap;
+import com.mybatisflex.core.mybatis.FlexConfiguration;
+import com.mybatisflex.core.mybatis.FlexSqlSessionFactoryBuilder;
+import com.mybatisflex.core.row.RowMapperInvoker;
+import com.mybatisflex.solon.transaction.MybatisMapperInterceptor;
+import com.mybatisflex.solon.transaction.SolonManagedTransactionFactory;
+import org.apache.ibatis.builder.xml.XMLMapperBuilder;
+import org.apache.ibatis.executor.ErrorContext;
+import org.apache.ibatis.io.Resources;
+import org.apache.ibatis.mapping.Environment;
+import org.apache.ibatis.plugin.Interceptor;
+import org.apache.ibatis.session.SqlSessionFactory;
+import org.apache.ibatis.session.SqlSessionFactoryBuilder;
+import org.apache.ibatis.transaction.TransactionFactory;
+import org.apache.ibatis.type.TypeHandler;
+import org.noear.solon.Utils;
+import org.noear.solon.annotation.Bean;
+import org.noear.solon.annotation.Condition;
+import org.noear.solon.annotation.Configuration;
+import org.noear.solon.annotation.Inject;
+import org.noear.solon.core.AppContext;
+import org.noear.solon.core.event.EventBus;
+import org.noear.solon.core.util.ResourceUtil;
+
+import javax.sql.DataSource;
+import java.io.InputStream;
+import java.lang.reflect.Proxy;
+
+/**
+ * Mybatis-Flex 自动装配
+ *
+ * @author noear 2024/12/17 created
+ */
+@Configuration
+public class MybatisFlexAutoConfiguration {
+ private DataSource getDataSource() {
+ return MybatisFlexBootstrap.getInstance().getDataSource();
+ }
+
+ @Inject
+ private AppContext appContext;
+
+ @Bean
+ public FlexConfiguration configuration(MybatisFlexProperties flexProperties,
+ @Inject(required = false) ConfigurationCustomizer configurationCustomizer) {
+ TransactionFactory tf = new SolonManagedTransactionFactory();
+ Environment environment = new Environment(FlexConsts.NAME, tf, getDataSource());
+
+ FlexConfiguration configuration = new FlexConfiguration(environment);
+
+ if (Utils.isNotEmpty(flexProperties.getConfigurationProperties())) {
+ Utils.injectProperties(configuration, flexProperties.getConfigurationProperties());
+ }
+
+ if (flexProperties.getConfiguration() != null) {
+ flexProperties.getConfiguration().applyTo(configuration);
+ }
+
+ if (configurationCustomizer != null) {
+ configurationCustomizer.customize(configuration);
+ }
+
+ //增加事件总线扩展
+ EventBus.publish(configuration);
+
+ return configuration;
+ }
+
+
+ @Bean
+ @Condition(onMissingBean = SqlSessionFactoryBuilder.class)
+ public SqlSessionFactoryBuilder sqlSessionFactoryBuilder() {
+ return new FlexSqlSessionFactoryBuilder();
+ }
+
+ @Bean
+ public SqlSessionFactory sqlSessionFactory(MybatisFlexProperties flexProperties,
+ FlexConfiguration flexConfiguration,
+ SqlSessionFactoryBuilder sqlSessionFactoryBuilder) {
+ appContext.subBeansOfType(Interceptor.class, bean -> {
+ flexConfiguration.addInterceptor(bean);
+ });
+
+ if (isNotEmpty(flexProperties.getTypeAliasesPackage())) {
+ Class> typeAliasesSuperType = flexProperties.getTypeAliasesSuperType();
+ for (String val : flexProperties.getTypeAliasesPackage()) {
+ //package || type class,转为类表达式
+ for (Class> clz : ResourceUtil.scanClasses(appContext.getClassLoader(), val)) {
+ if (isTypeAliases(clz, typeAliasesSuperType)) {
+ flexConfiguration.getTypeAliasRegistry().registerAlias(clz);
+ }
+ }
+ }
+ }
+
+ if (isNotEmpty(flexProperties.getTypeHandlersPackage())) {
+ for (String val : flexProperties.getTypeHandlersPackage()) {
+ for (Class> clz : ResourceUtil.scanClasses(appContext.getClassLoader(), val)) {
+ if (TypeHandler.class.isAssignableFrom(clz)) {
+ flexConfiguration.getTypeHandlerRegistry().register(clz);
+ }
+ }
+ }
+ }
+
+ if (isNotEmpty(flexProperties.getMapperLocations())) {
+ for (String val : flexProperties.getMapperLocations()) {
+ if (ResourceUtil.hasClasspath(val)) {
+ //mapper xml, 新方法,替代旧的 *.xml (基于表达式;更自由,更语义化)
+ for (String uri : ResourceUtil.scanResources(val)) {
+ addMapperByXml(flexConfiguration, uri);
+ }
+ } else {
+ //package || type class,转为类表达式
+ for (Class> clz : ResourceUtil.scanClasses(appContext.getClassLoader(), val)) {
+ if (clz.isInterface()) {
+ //no mapperVerifyEnabled ...
+ flexConfiguration.addMapper(clz);
+ }
+ }
+ }
+ }
+
+ //如果有配置,但是没有 mapper 注册成功;说明有问题了
+ if (flexConfiguration.getMapperRegistry().getMappers().size() == 0) {
+ throw new IllegalStateException("Missing mapper registration, please check the 'mapperLocations' configuration!");
+ }
+ }
+
+ return sqlSessionFactoryBuilder.build(flexConfiguration);
+ }
+
+ @Bean
+ public FlexGlobalConfig globalConfig(MybatisFlexProperties flexProperties,
+ FlexConfiguration flexConfiguration,
+ SqlSessionFactory sqlSessionFactory,
+ @Inject(required = false) MyBatisFlexCustomizer flexCustomizer) {
+
+ FlexGlobalConfig globalConfig = FlexGlobalConfig.getDefaultConfig();
+
+ if (flexProperties.getGlobalConfig() != null) {
+ flexProperties.getGlobalConfig().applyTo(globalConfig);
+ }
+
+ if (globalConfig.getKeyConfig() == null) {
+ //如果没有,给个默认值
+ globalConfig.setKeyConfig(new FlexGlobalConfig.KeyConfig());
+ }
+
+ globalConfig.setConfiguration(flexConfiguration);
+ globalConfig.setSqlSessionFactory(sqlSessionFactory);
+
+ if (flexCustomizer != null) {
+ flexCustomizer.customize(globalConfig);
+ }
+
+ //增加事件总线扩展
+ EventBus.publish(globalConfig);
+
+ return globalConfig;
+ }
+
+ @Bean
+ public void mapperPublish(FlexConfiguration flexConfiguration,
+ FlexGlobalConfig globalConfig,
+ SqlSessionFactory sqlSessionFactory) {
+ for (Class> mapperClz : flexConfiguration.getMapperRegistry().getMappers()) {
+ MybatisMapperInterceptor handler = new MybatisMapperInterceptor(sqlSessionFactory, mapperClz);
+
+ Object mapperProxy = Proxy.newProxyInstance(
+ mapperClz.getClassLoader(),
+ new Class[]{mapperClz},
+ handler);
+
+ //推入容器,之后可以被注入
+ appContext.wrapAndPut(mapperClz, mapperProxy);
+ }
+ }
+
+ @Bean
+ public RowMapperInvoker rowMapperInvoker(SqlSessionFactory sqlSessionFactory) {
+ return new RowMapperInvoker(sqlSessionFactory);
+ }
+
+ /////////////
+
+ /**
+ * 添加 xml mapper
+ */
+ private void addMapperByXml(FlexConfiguration flexConfiguration, String uri) {
+ try {
+ // resource 配置方式
+ ErrorContext.instance().resource(uri);
+
+ //读取mapper文件
+ InputStream stream = Resources.getResourceAsStream(uri);
+
+ //mapper映射文件都是通过XMLMapperBuilder解析
+ XMLMapperBuilder mapperParser = new XMLMapperBuilder(stream, flexConfiguration, uri, flexConfiguration.getSqlFragments());
+ mapperParser.parse();
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
+ * 是否为非空数组
+ */
+ private boolean isNotEmpty(String[] ary) {
+ return ary != null && ary.length > 0;
+ }
+
+ /**
+ * 是否为类型别名
+ */
+ private boolean isTypeAliases(Class> clz, Class> typeAliasesSuperType) {
+ if (clz.isInterface()) {
+ return false;
+ }
+
+ if (typeAliasesSuperType != null) {
+ return typeAliasesSuperType.isAssignableFrom(clz);
+ } else {
+ return true;
+ }
+ }
+}
diff --git a/mybatis-flex-solon-plugin/src/main/java/com/mybatisflex/solon/MybatisFlexProperties.java b/mybatis-flex-solon-plugin/src/main/java/com/mybatisflex/solon/MybatisFlexProperties.java
index 661e7efd..a5c90e90 100644
--- a/mybatis-flex-solon-plugin/src/main/java/com/mybatisflex/solon/MybatisFlexProperties.java
+++ b/mybatis-flex-solon-plugin/src/main/java/com/mybatisflex/solon/MybatisFlexProperties.java
@@ -24,13 +24,11 @@ import org.apache.ibatis.scripting.LanguageDriver;
import org.apache.ibatis.session.*;
import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.TypeHandler;
+import org.noear.solon.annotation.Inject;
import org.noear.solon.core.util.ResourceUtil;
import java.net.URI;
-import java.util.Map;
-import java.util.Optional;
-import java.util.Properties;
-import java.util.Set;
+import java.util.*;
import java.util.stream.Stream;
/**
@@ -42,6 +40,8 @@ import java.util.stream.Stream;
* @author micahel
* @author 王帅
*/
+@org.noear.solon.annotation.Configuration
+@Inject("${mybatisFlex}")
public class MybatisFlexProperties {
private String defaultDatasourceKey;
@@ -77,7 +77,7 @@ public class MybatisFlexProperties {
/**
* Packages to search type aliases. (Package delimiters are ",; \t\n")
*/
- private String typeAliasesPackage;
+ private String[] typeAliasesPackage;
/**
* The super class for filtering type alias. If this not specifies, the MyBatis deal as type alias all classes that
@@ -88,7 +88,7 @@ public class MybatisFlexProperties {
/**
* Packages to search for type handlers. (Package delimiters are ",; \t\n")
*/
- private String typeHandlersPackage;
+ private String[] typeHandlersPackage;
/**
* Indicates whether perform presence check of the MyBatis xml config file.
@@ -183,19 +183,19 @@ public class MybatisFlexProperties {
this.mapperLocations = mapperLocations;
}
- public String getTypeHandlersPackage() {
+ public String[] getTypeHandlersPackage() {
return this.typeHandlersPackage;
}
- public void setTypeHandlersPackage(String typeHandlersPackage) {
+ public void setTypeHandlersPackage(String[] typeHandlersPackage) {
this.typeHandlersPackage = typeHandlersPackage;
}
- public String getTypeAliasesPackage() {
+ public String[] getTypeAliasesPackage() {
return this.typeAliasesPackage;
}
- public void setTypeAliasesPackage(String typeAliasesPackage) {
+ public void setTypeAliasesPackage(String[] typeAliasesPackage) {
this.typeAliasesPackage = typeAliasesPackage;
}
diff --git a/mybatis-flex-solon-plugin/src/main/java/com/mybatisflex/solon/annotation/UseDataSourceInterceptor.java b/mybatis-flex-solon-plugin/src/main/java/com/mybatisflex/solon/annotation/UseDataSourceInterceptor.java
new file mode 100644
index 00000000..0ab8ee75
--- /dev/null
+++ b/mybatis-flex-solon-plugin/src/main/java/com/mybatisflex/solon/annotation/UseDataSourceInterceptor.java
@@ -0,0 +1,35 @@
+package com.mybatisflex.solon.annotation;
+
+import com.mybatisflex.annotation.UseDataSource;
+import com.mybatisflex.core.datasource.DataSourceKey;
+import org.noear.solon.core.aspect.Invocation;
+import org.noear.solon.core.aspect.MethodInterceptor;
+import org.noear.solon.core.util.TmplUtil;
+
+/**
+ * @author noear 2024/12/17 created
+ */
+public class UseDataSourceInterceptor implements MethodInterceptor {
+ @Override
+ public Object doIntercept(Invocation inv) throws Throwable {
+ UseDataSource anno = inv.getMethodAnnotation(UseDataSource.class);
+
+ if (anno == null) {
+ anno = inv.getTargetAnnotation(UseDataSource.class);
+ }
+
+ if (anno == null) {
+ return inv.invoke();
+ } else {
+ String dsName = TmplUtil.parse(anno.value(), inv);
+ DataSourceKey.use(dsName);
+
+ try {
+ return inv.invoke();
+ } finally {
+ //还原
+ DataSourceKey.clear();
+ }
+ }
+ }
+}
diff --git a/mybatis-flex-solon-plugin/src/main/java/com/mybatisflex/solon/aot/MybatisRuntimeNativeRegistrar.java b/mybatis-flex-solon-plugin/src/main/java/com/mybatisflex/solon/aot/MybatisRuntimeNativeRegistrar.java
index 47f81990..dda7bc01 100644
--- a/mybatis-flex-solon-plugin/src/main/java/com/mybatisflex/solon/aot/MybatisRuntimeNativeRegistrar.java
+++ b/mybatis-flex-solon-plugin/src/main/java/com/mybatisflex/solon/aot/MybatisRuntimeNativeRegistrar.java
@@ -1,7 +1,7 @@
package com.mybatisflex.solon.aot;
-import com.mybatisflex.solon.integration.XPluginImpl;
-import com.mybatisflex.solon.mybtais.MybatisAdapterDefault;
+import com.mybatisflex.core.mybatis.FlexConfiguration;
+import com.mybatisflex.solon.MybatisFlexProperties;
import org.apache.ibatis.cache.decorators.FifoCache;
import org.apache.ibatis.cache.decorators.LruCache;
import org.apache.ibatis.cache.decorators.SoftCache;
@@ -25,6 +25,7 @@ import org.apache.ibatis.scripting.defaults.RawLanguageDriver;
import org.apache.ibatis.scripting.xmltags.XMLLanguageDriver;
import org.apache.ibatis.session.Configuration;
import org.apache.ibatis.session.SqlSessionFactory;
+import org.apache.ibatis.type.TypeHandler;
import org.noear.solon.aot.NativeMetadataUtils;
import org.noear.solon.aot.RuntimeNativeMetadata;
import org.noear.solon.aot.RuntimeNativeRegistrar;
@@ -98,40 +99,49 @@ public class MybatisRuntimeNativeRegistrar implements RuntimeNativeRegistrar {
metadata.registerReflection(DefaultVFS.class, MemberCategory.INVOKE_PUBLIC_CONSTRUCTORS);
- registerMybatisAdapter(context, metadata, XPluginImpl.getAdapterFlex());
+ registerMybatisAdapter(context, metadata);
}
- protected void registerMybatisAdapter(AppContext context, RuntimeNativeMetadata metadata, MybatisAdapterDefault bean) {
- if (bean == null) {
- return;
- }
+ protected void registerMybatisAdapter(AppContext context, RuntimeNativeMetadata metadata) {
+ MybatisFlexProperties flexProperties = context.getBean(MybatisFlexProperties.class);
//注册 xml 资源
- for (String res : bean.getMappers()) {
- if (res.startsWith(ResourceUtil.TAG_classpath)) {
- res = res.substring(ResourceUtil.TAG_classpath.length());
- res = res.replace("**", "*");
- res = res.replace("*", ".*");
- metadata.registerResourceInclude(res);
+ if (flexProperties != null) {
+ for (String res : flexProperties.getMapperLocations()) {
+ if (ResourceUtil.hasClasspath(res)) {
+ res = ResourceUtil.remSchema(res);
+ res = res.replace("**", "*");
+ res = res.replace("*", ".*");
+ metadata.registerResourceInclude(res);
+ }
}
}
- //注册 mapper 代理
- for (Class> clz : bean.getConfiguration().getMapperRegistry().getMappers()) {
- metadata.registerJdkProxy(clz);
- metadata.registerReflection(clz, MemberCategory.INTROSPECT_PUBLIC_METHODS);
- Method[] declaredMethods = clz.getDeclaredMethods();
- for (Method method : declaredMethods) {
- MethodWrap methodWrap = context.methodGet(method);
- NativeMetadataUtils.registerMethodAndParamAndReturnType(metadata, methodWrap);
+ FlexConfiguration flexConfiguration = context.getBean(FlexConfiguration.class);
+ if (flexConfiguration != null) {
+ //注册 mapper 代理
+ for (Class> clz : flexConfiguration.getMapperRegistry().getMappers()) {
+ metadata.registerJdkProxy(clz);
+ metadata.registerReflection(clz, MemberCategory.INTROSPECT_PUBLIC_METHODS);
+ Method[] declaredMethods = clz.getDeclaredMethods();
+ for (Method method : declaredMethods) {
+ MethodWrap methodWrap = context.methodGet(method);
+ NativeMetadataUtils.registerMethodAndParamAndReturnType(metadata, methodWrap);
+ }
}
- }
- // 注册 entity
- for (Class> clz : bean.getConfiguration().getTypeAliasRegistry().getTypeAliases().values()) {
- metadata.registerReflection(clz, MemberCategory.DECLARED_FIELDS, MemberCategory.INVOKE_PUBLIC_CONSTRUCTORS);
- metadata.registerDefaultConstructor(clz);
+ // 注册 entity
+ for (Class> clz : flexConfiguration.getTypeAliasRegistry().getTypeAliases().values()) {
+ metadata.registerReflection(clz, MemberCategory.DECLARED_FIELDS, MemberCategory.INVOKE_PUBLIC_CONSTRUCTORS);
+ metadata.registerDefaultConstructor(clz);
+ }
+
+ //注处 typeHandler
+ for (TypeHandler typeHandler : flexConfiguration.getTypeHandlerRegistry().getTypeHandlers()) {
+ metadata.registerReflection(typeHandler.getClass(), MemberCategory.DECLARED_FIELDS, MemberCategory.INVOKE_PUBLIC_CONSTRUCTORS);
+ metadata.registerDefaultConstructor(typeHandler.getClass());
+ }
}
}
}
diff --git a/mybatis-flex-solon-plugin/src/main/java/com/mybatisflex/solon/integration/MybatisAdapterFlex.java b/mybatis-flex-solon-plugin/src/main/java/com/mybatisflex/solon/integration/MybatisAdapterFlex.java
deleted file mode 100644
index a99eb3c6..00000000
--- a/mybatis-flex-solon-plugin/src/main/java/com/mybatisflex/solon/integration/MybatisAdapterFlex.java
+++ /dev/null
@@ -1,170 +0,0 @@
-/*
- * Copyright (c) 2022-2025, Mybatis-Flex (fuhai999@gmail.com).
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.mybatisflex.solon.integration;
-
-import com.mybatisflex.core.FlexGlobalConfig;
-import com.mybatisflex.core.mybatis.FlexConfiguration;
-import com.mybatisflex.core.mybatis.FlexSqlSessionFactoryBuilder;
-import com.mybatisflex.core.row.RowMapperInvoker;
-import com.mybatisflex.solon.MybatisFlexProperties;
-import com.mybatisflex.solon.mybtais.MybatisAdapterDefault;
-import org.apache.ibatis.mapping.Environment;
-import org.apache.ibatis.session.SqlSessionFactory;
-import org.noear.solon.Utils;
-import org.noear.solon.core.BeanWrap;
-import org.noear.solon.core.Props;
-import org.noear.solon.core.VarHolder;
-import org.noear.solon.core.event.EventBus;
-
-import javax.sql.DataSource;
-
-/**
- * MyBatis-Flex 适配器。
- *
- * @author noear
- * @since 2.2
- */
-public class MybatisAdapterFlex extends MybatisAdapterDefault {
- private FlexSqlSessionFactoryBuilder factoryBuilderPlus;
- private FlexGlobalConfig globalConfig;
- private RowMapperInvoker rowMapperInvoker;
- private Class> typeAliasesBaseType;
- private MybatisFlexProperties flexProperties;
-
- protected MybatisAdapterFlex(BeanWrap dsWrap, Props flexProps, MybatisFlexProperties flexProperties) {
- this.factoryBuilderPlus = new FlexSqlSessionFactoryBuilder();
- this.flexProperties = flexProperties;
-
- //初始化开始
- initStart(dsWrap, flexProps);
-
- //初始化之前
- initAfter(dsWrap);
- }
-
- protected void initAfter(BeanWrap dsWrap) {
- globalConfig.setSqlSessionFactory(getFactory());
- }
-
- @Override
- protected DataSource getDataSource() {
- return dsWrap.raw();
- }
-
- @Override
- protected void initConfiguration(Environment environment) {
- //for configuration section
- config = new FlexConfiguration(environment);
-
- if (Utils.isNotEmpty(flexProperties.getConfigurationProperties())) {
- Utils.injectProperties(config, flexProperties.getConfigurationProperties());
- }
-
- if (flexProperties.getConfiguration() != null) {
- flexProperties.getConfiguration().applyTo(config);
- }
-
- //for globalConfig section
- if (dsWrap.typed()) {
- globalConfig = FlexGlobalConfig.getDefaultConfig();
- } else {
- globalConfig = new FlexGlobalConfig();
- }
-
- if (flexProperties.getGlobalConfig() != null) {
- flexProperties.getGlobalConfig().applyTo(globalConfig);
- }
-
- if (globalConfig.getKeyConfig() == null) {
- //如果没有,给个默认值
- globalConfig.setKeyConfig(new FlexGlobalConfig.KeyConfig());
- }
-
- globalConfig.setConfiguration(config);
-
- FlexGlobalConfig.setConfig(environment.getId(), globalConfig, false);
-
- //增加事件扩展机制
- EventBus.publish(globalConfig);
- }
-
- @Override
- protected void loadConfiguration() {
- typeAliasesBaseType = flexProperties.getTypeAliasesSuperType();
- super.loadConfiguration();
- }
-
- /**
- * 获取全局配置
- */
- public FlexGlobalConfig getGlobalConfig() {
- return globalConfig;
- }
-
- @Override
- public SqlSessionFactory getFactory() {
- if (factory == null) {
- factory = factoryBuilderPlus.build(getConfiguration());
- }
-
- return factory;
- }
-
- @Override
- public void injectTo(VarHolder varH) {
- super.injectTo(varH);
-
- // @Db("db1") FlexGlobalConfig globalConfig
- if (FlexGlobalConfig.class.isAssignableFrom(varH.getType())) {
- varH.setValue(this.getGlobalConfig());
- return;
- }
-
- // @Db("db1") RowMapperInvoker rowMapper
- if (RowMapperInvoker.class.equals(varH.getType())) {
- if (rowMapperInvoker == null) {
- rowMapperInvoker = new RowMapperInvoker(getFactory());
- }
- varH.setValue(rowMapperInvoker);
- }
- }
-
- @Override
- protected boolean isTypeAliasesType(Class> type) {
- //typeAliasesSuperType
- if (typeAliasesBaseType == null) {
- return true;
- } else {
- return typeAliasesBaseType.isAssignableFrom(type);
- }
- }
-
- @Override
- protected boolean isTypeAliasesKey(String key) {
- return super.isTypeAliasesKey(key) || key.startsWith("typeAliasesPackage[");
- }
-
- @Override
- protected boolean isTypeHandlersKey(String key) {
- return super.isTypeHandlersKey(key) || key.startsWith("typeHandlersPackage[");
- }
-
- @Override
- protected boolean isMappersKey(String key) {
- return super.isMappersKey(key) || key.startsWith("mapperLocations[");
- }
-}
diff --git a/mybatis-flex-solon-plugin/src/main/java/com/mybatisflex/solon/integration/XPluginImpl.java b/mybatis-flex-solon-plugin/src/main/java/com/mybatisflex/solon/integration/MybatisFlexPlugin.java
similarity index 54%
rename from mybatis-flex-solon-plugin/src/main/java/com/mybatisflex/solon/integration/XPluginImpl.java
rename to mybatis-flex-solon-plugin/src/main/java/com/mybatisflex/solon/integration/MybatisFlexPlugin.java
index 7b913e0c..100052cc 100644
--- a/mybatis-flex-solon-plugin/src/main/java/com/mybatisflex/solon/integration/XPluginImpl.java
+++ b/mybatis-flex-solon-plugin/src/main/java/com/mybatisflex/solon/integration/MybatisFlexPlugin.java
@@ -17,35 +17,30 @@
package com.mybatisflex.solon.integration;
import com.mybatisflex.annotation.UseDataSource;
-import com.mybatisflex.core.FlexConsts;
-import com.mybatisflex.core.FlexGlobalConfig;
import com.mybatisflex.core.MybatisFlexBootstrap;
import com.mybatisflex.core.datasource.*;
import com.mybatisflex.core.logicdelete.LogicDeleteManager;
import com.mybatisflex.core.logicdelete.LogicDeleteProcessor;
-import com.mybatisflex.core.mybatis.FlexConfiguration;
-import com.mybatisflex.core.row.RowMapperInvoker;
import com.mybatisflex.core.table.DynamicSchemaProcessor;
import com.mybatisflex.core.table.DynamicTableProcessor;
import com.mybatisflex.core.table.TableManager;
import com.mybatisflex.core.tenant.TenantFactory;
import com.mybatisflex.core.tenant.TenantManager;
+import com.mybatisflex.solon.MybatisFlexAutoConfiguration;
import com.mybatisflex.solon.MybatisFlexProperties;
+import com.mybatisflex.solon.annotation.UseDataSourceInterceptor;
import com.mybatisflex.solon.aot.MybatisRuntimeNativeRegistrar;
-import org.apache.ibatis.session.SqlSessionFactory;
import org.noear.solon.Utils;
-import org.noear.solon.annotation.Inject;
import org.noear.solon.aot.RuntimeNativeRegistrar;
import org.noear.solon.core.AppContext;
import org.noear.solon.core.BeanWrap;
import org.noear.solon.core.Plugin;
-import org.noear.solon.core.Props;
import org.noear.solon.core.runtime.NativeDetector;
import org.noear.solon.core.util.ClassUtil;
-import org.noear.solon.core.util.TmplUtil;
import javax.sql.DataSource;
import java.util.Map;
+import java.util.concurrent.atomic.AtomicBoolean;
/**
* 配置 MyBatis-Flex 插件。
@@ -53,65 +48,15 @@ import java.util.Map;
* @author noear
* @since 2.2
*/
-public class XPluginImpl implements Plugin {
- private static final String CONFIG_PREFIX = "mybatisFlex.";
-
- private static MybatisAdapterFlex adapterFlex;
-
- public static MybatisAdapterFlex getAdapterFlex() {
- return adapterFlex;
- }
-
- private Props flexProps;
- private MybatisFlexProperties flexProperties;
-
+public class MybatisFlexPlugin implements Plugin {
@Override
public void start(AppContext context) throws Throwable {
// 注册动态数据源的事务路由
//TranManager.routing(FlexDataSource.class, new FlexDataSourceRouting());
- flexProps = context.cfg().getProp(CONFIG_PREFIX);
- flexProperties = flexProps.toBean(MybatisFlexProperties.class);
- if (flexProperties == null) {
- flexProperties = new MybatisFlexProperties();
- }
+ MybatisFlexProperties flexProperties = context.beanMake(MybatisFlexProperties.class).get();
- //数据源解密器
- context.getBeanAsync(DataSourceDecipher.class, bean->{
- DataSourceManager.setDecipher(bean);
- });
-
- // 动态表名配置
- context.getBeanAsync(DynamicTableProcessor.class, bean->{
- TableManager.setDynamicTableProcessor(bean);
- });
-
- // 动态 schema 处理器配置
- context.getBeanAsync(DynamicSchemaProcessor.class, bean->{
- TableManager.setDynamicSchemaProcessor(bean);
- });
-
- //多租户
- context.getBeanAsync(TenantFactory.class, bean->{
- TenantManager.setTenantFactory(bean);
- });
-
- //逻辑删除处理器
- context.getBeanAsync(LogicDeleteProcessor.class, bean->{
- LogicDeleteManager.setProcessor(bean);
- });
-
- // 订阅数据源
- context.subWrapsOfType(DataSource.class, bw -> {
- loadDs(context, bw);
- });
-
- // aot
- if (NativeDetector.isAotRuntime() && ClassUtil.hasClass(() -> RuntimeNativeRegistrar.class)) {
- context.wrapAndPut(MybatisRuntimeNativeRegistrar.class);
- }
-
- // 构建 mf 配置的数据源
+ // 构建 flexProperties 配置的数据源(并推入应用上下文,可供其它工具使用)
if (Utils.isNotEmpty(flexProperties.getDatasource())) {
for (Map.Entry> entry : flexProperties.getDatasource().entrySet()) {
String dsName = entry.getKey();
@@ -124,10 +69,49 @@ public class XPluginImpl implements Plugin {
context.wrapPublish(bw);
}
}
+
+ // UseDataSource 拦截器(aop)
+ context.beanInterceptorAdd(UseDataSource.class, new UseDataSourceInterceptor());
+
+ // 数据源解密器
+ context.getBeanAsync(DataSourceDecipher.class, bean -> {
+ DataSourceManager.setDecipher(bean);
+ });
+
+ // 动态表名配置
+ context.getBeanAsync(DynamicTableProcessor.class, bean -> {
+ TableManager.setDynamicTableProcessor(bean);
+ });
+
+ // 动态 schema 处理器配置
+ context.getBeanAsync(DynamicSchemaProcessor.class, bean -> {
+ TableManager.setDynamicSchemaProcessor(bean);
+ });
+
+ //多租户
+ context.getBeanAsync(TenantFactory.class, bean -> {
+ TenantManager.setTenantFactory(bean);
+ });
+
+ //逻辑删除处理器
+ context.getBeanAsync(LogicDeleteProcessor.class, bean -> {
+ LogicDeleteManager.setProcessor(bean);
+ });
+
+ // 订阅数据源
+ context.subWrapsOfType(DataSource.class, bw -> {
+ loadDs(context, bw);
+ });
+
+ // aot
+ if (NativeDetector.isAotRuntime() && ClassUtil.hasClass(() -> RuntimeNativeRegistrar.class)) {
+ context.wrapAndPut(MybatisRuntimeNativeRegistrar.class);
+ }
}
+ private AtomicBoolean initialized = new AtomicBoolean(false);
+
private void loadDs(AppContext context, BeanWrap bw) {
- boolean isInit = MybatisFlexBootstrap.getInstance().getDataSource() == null;
MybatisFlexBootstrap.getInstance().addDataSource(bw.name(), bw.raw());
if (bw.typed()) {
@@ -136,61 +120,9 @@ public class XPluginImpl implements Plugin {
flexDataSource.setDefaultDataSource(bw.name());
}
- if (isInit) {
- initDo(context);
+ if (initialized.compareAndSet(false, true)) {
+ //有数据源后,再启动自动装配
+ context.beanMake(MybatisFlexAutoConfiguration.class);
}
}
-
- private void initDo(AppContext context) {
- BeanWrap dsBw = context.wrap(FlexConsts.NAME, MybatisFlexBootstrap.getInstance().getDataSource(), true);
- MybatisAdapterFlex dsFlex = new MybatisAdapterFlex(dsBw, flexProps, flexProperties);
- dsFlex.mapperPublish();
- adapterFlex = dsFlex;
-
- // 注册到管理器(aot 时会用到)
- //MybatisAdapterManager.register(dsBw, dsFlex);
-
- //绑定到容器
- context.beanInjectorAdd(Inject.class, FlexGlobalConfig.class, ((vh, anno) -> {
- dsFlex.injectTo(vh);
- }));
-
-
- context.beanInjectorAdd(Inject.class, FlexConfiguration.class, ((vh, anno) -> {
- dsFlex.injectTo(vh);
- }));
-
- context.beanInjectorAdd(Inject.class, RowMapperInvoker.class, ((vh, anno) -> {
- dsFlex.injectTo(vh);
- }));
-
- context.beanInjectorAdd(Inject.class, SqlSessionFactory.class, ((vh, anno) -> {
- dsFlex.injectTo(vh);
- }));
-
- context.beanInterceptorAdd(UseDataSource.class, inv -> {
- UseDataSource anno = inv.getMethodAnnotation(UseDataSource.class);
-
- if (anno == null) {
- anno = inv.getTargetAnnotation(UseDataSource.class);
- }
-
- if (anno == null) {
- return inv.invoke();
- } else {
- //备份
- String backup = DataSourceKey.get();
-
- try {
- String dsName = TmplUtil.parse(anno.value(), inv);
-
- DataSourceKey.use(dsName);
- return inv.invoke();
- } finally {
- //还原
- DataSourceKey.use(backup);
- }
- }
- });
- }
}
diff --git a/mybatis-flex-solon-plugin/src/main/java/com/mybatisflex/solon/mybtais/MybatisAdapterDefault.java b/mybatis-flex-solon-plugin/src/main/java/com/mybatisflex/solon/mybtais/MybatisAdapterDefault.java
deleted file mode 100644
index 68f205eb..00000000
--- a/mybatis-flex-solon-plugin/src/main/java/com/mybatisflex/solon/mybtais/MybatisAdapterDefault.java
+++ /dev/null
@@ -1,351 +0,0 @@
-package com.mybatisflex.solon.mybtais;
-
-import org.apache.ibatis.annotations.Mapper;
-import org.apache.ibatis.builder.xml.XMLMapperBuilder;
-import org.apache.ibatis.executor.ErrorContext;
-import org.apache.ibatis.io.Resources;
-import org.apache.ibatis.mapping.Environment;
-import org.apache.ibatis.plugin.Interceptor;
-import org.apache.ibatis.session.Configuration;
-import org.apache.ibatis.session.SqlSessionFactory;
-import org.apache.ibatis.session.SqlSessionFactoryBuilder;
-import org.apache.ibatis.transaction.TransactionFactory;
-import org.apache.ibatis.type.TypeHandler;
-import org.noear.solon.Utils;
-import org.noear.solon.core.BeanWrap;
-import org.noear.solon.core.LifecycleIndex;
-import org.noear.solon.core.Props;
-import org.noear.solon.core.VarHolder;
-import org.noear.solon.core.event.EventBus;
-import org.noear.solon.core.util.ResourceUtil;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import javax.sql.DataSource;
-import java.io.InputStream;
-import java.lang.reflect.Proxy;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-/**
- * Mybatis 适配器默认实现
- *
- * @author noear
- * @since 1.1
- */
-public class MybatisAdapterDefault {
- protected static final Logger log = LoggerFactory.getLogger(MybatisAdapterDefault.class);
-
- protected BeanWrap dsWrap;
- protected Props dsProps;
-
- //mapper 注解验证启用?
- protected boolean mapperVerifyEnabled;
-
- protected Configuration config;
- protected SqlSessionFactory factory;
- protected List mappers = new ArrayList<>();
- protected SqlSessionFactoryBuilder factoryBuilder;
-
- /**
- * 构建Sql工厂适配器,使用属性配置
- */
- protected void initStart(BeanWrap dsWrap, Props dsProps) {
- this.dsWrap = dsWrap;
- if (dsProps == null) {
- this.dsProps = new Props();
- } else {
- this.dsProps = dsProps;
- }
-
- this.mapperVerifyEnabled = dsProps.getBool("configuration.mapperVerifyEnabled", false);
- this.factoryBuilder = new SqlSessionFactoryBuilder();
-
- DataSource dataSource = getDataSource();
- String dataSourceId = dsWrap.name();
- if (Utils.isEmpty(dataSourceId)) {
- dataSourceId = "_main";
- }
-
- TransactionFactory tf = new SolonManagedTransactionFactory();
- Environment environment = new Environment(dataSourceId, tf, dataSource);
-
- //1.初始化配置器
- initConfiguration(environment);
-
- //加载插件(通过Bean)
- dsWrap.context().lifecycle(LifecycleIndex.PLUGIN_BEAN_USES, () -> {
- dsWrap.context().beanForeach(bw -> {
- if (bw.raw() instanceof Interceptor) {
- config.addInterceptor(bw.raw());
- }
- });
- });
-
- //2.分发事件,推给扩展处理
- EventBus.publish(config);
-
- //3.加载配置器的内容(顺序不能乱)
- loadConfiguration();
-
- dsWrap.context().getBeanAsync(SqlSessionFactoryBuilder.class, bean -> {
- factoryBuilder = bean;
- });
- }
-
- public List getMappers() {
- return mappers;
- }
-
- protected DataSource getDataSource() {
- return dsWrap.raw();
- }
-
- protected void initConfiguration(Environment environment) {
- config = new Configuration(environment);
-
- //for configuration section
- Props cfgProps = dsProps.getProp("configuration");
- if (cfgProps.size() > 0) {
- Utils.injectProperties(config, cfgProps);
- }
- }
-
- protected boolean isTypeAliasesType(Class> type) {
- return true;
- }
-
- protected boolean isTypeAliasesKey(String key) {
- return key.startsWith("typeAliases[") || key.equals("typeAliases");
- }
-
- protected boolean isTypeHandlersKey(String key) {
- return key.startsWith("typeHandlers[") || key.equals("typeHandlers");
- }
-
- protected boolean isMappersKey(String key) {
- return key.startsWith("mappers[") || key.equals("mappers");
- }
-
- protected void loadConfiguration() {
- //for typeAliases & typeHandlers section
- dsProps.forEach((k, v) -> {
- if (k instanceof String && v instanceof String) {
- String key = (String) k;
- String valStr = (String) v;
-
- if (isTypeAliasesKey(key)) {
- for (String val : valStr.split(",")) {
- val = val.trim();
- if (val.length() == 0) {
- continue;
- }
-
- //package || type class,转为类表达式
- for (Class> clz : ResourceUtil.scanClasses(dsWrap.context().getClassLoader(), val)) {
- if (clz.isInterface() == false) {
- if (isTypeAliasesType(clz)) {
- getConfiguration().getTypeAliasRegistry().registerAlias(clz);
- }
- }
- }
- }
- }
-
- if (isTypeHandlersKey(key)) {
- for (String val : valStr.split(",")) {
- val = val.trim();
- if (val.length() == 0) {
- continue;
- }
-
- //package || type class,转为类表达式
- for (Class> clz : ResourceUtil.scanClasses(dsWrap.context().getClassLoader(), val)) {
- if (TypeHandler.class.isAssignableFrom(clz)) {
- getConfiguration().getTypeHandlerRegistry().register(clz);
- }
- }
- }
- }
- }
- });
-
- //todo: 上面的完成后,才能做下面这个
-
- //for mappers section
- dsProps.forEach((k, v) -> {
- if (k instanceof String && v instanceof String) {
- String key = (String) k;
- String valStr = (String) v;
-
- if (isMappersKey(key)) {
- for (String val : valStr.split(",")) {
- val = val.trim();
- if (val.length() == 0) {
- continue;
- }
-
- mappers.add(val);
-
- if (ResourceUtil.hasClasspath(val)) {
- //mapper xml, 新方法,替代旧的 *.xml (基于表达式;更自由,更语义化)
- for (String uri : ResourceUtil.scanResources(val)) {
- addMapperByXml(uri);
- }
-
- //todo: 兼容提醒:
- compatibilityTipsOfXml(val);
- } else {
- //package || type class,转为类表达式
- for (Class> clz : ResourceUtil.scanClasses(dsWrap.context().getClassLoader(), val)) {
- if (clz.isInterface()) {
- if (mapperVerifyEnabled) {
- if (isMapper(clz)) {
- getConfiguration().addMapper(clz);
- }
- } else {
- getConfiguration().addMapper(clz);
- }
- }
- }
- }
- }
- }
- }
- });
-
- if (mappers.size() == 0) {
- if (Utils.isEmpty(dsWrap.name())) {
- log.warn("Mybatis: Missing mappers configuration!");
- } else {
- log.warn("Mybatis: Missing mappers configuration. name='{}'", dsWrap.name());
- }
- //throw new IllegalStateException("Please add the mappers configuration!");
- } else {
- //如果有配置,但是没有 mapper 注册成功;说明有问题了
- if (config.getMapperRegistry().getMappers().size() == 0) {
- //log.warn("Mybatis: Missing mapper registration, please check the mappers configuration!");
- if (Utils.isEmpty(dsWrap.name())) {
- throw new IllegalStateException("Missing mapper registration, please check the mappers configuration!");
- } else {
- throw new IllegalStateException("Missing mapper registration, please check the mappers configuration. name='" + dsWrap.name() + "'");
- }
- }
- }
-
- //for plugins section
- List interceptors = MybatisPluginUtils.resolve(dsProps, "plugins");
- for (Interceptor itp : interceptors) {
- getConfiguration().addInterceptor(itp);
- }
- }
-
- protected boolean isMapper(Class> clz) {
- return clz.isAnnotationPresent(Mapper.class);
- }
-
- /**
- * 获取配置器
- */
- public Configuration getConfiguration() {
- return config;
- }
-
- /**
- * 获取会话工厂
- */
- public SqlSessionFactory getFactory() {
- if (factory == null) {
- factory = factoryBuilder.build(getConfiguration());//new SqlSessionFactoryProxy(factoryBuilder.build(config));
- }
-
- return factory;
- }
-
- Map, Object> mapperCached = new HashMap<>();
-
- public T getMapper(Class mapperClz) {
- Object mapper = mapperCached.get(mapperClz);
-
- if (mapper == null) {
- synchronized (mapperClz) {
- mapper = mapperCached.get(mapperClz);
- if (mapper == null) {
- MybatisMapperInterceptor handler = new MybatisMapperInterceptor(getFactory(), mapperClz);
-
- mapper = Proxy.newProxyInstance(
- mapperClz.getClassLoader(),
- new Class[]{mapperClz},
- handler);
- mapperCached.put(mapperClz, mapper);
- }
- }
- }
-
- return (T) mapper;
- }
-
- public void injectTo(VarHolder vh) {
- //@Db("db1") SqlSessionFactory factory;
- if (SqlSessionFactory.class.isAssignableFrom(vh.getType())) {
- vh.setValue(this.getFactory());
- return;
- }
-
- //@Db("db1") Configuration cfg;
- if (Configuration.class.isAssignableFrom(vh.getType())) {
- vh.setValue(this.getConfiguration());
- return;
- }
-
- //@Db("db1") UserMapper userMapper;
- if (vh.getType().isInterface()) {
- Object mapper = this.getMapper(vh.getType());
-
- vh.setValue(mapper);
- return;
- }
- }
-
- protected void addMapperByXml(String uri) {
- try {
- // resource 配置方式
- ErrorContext.instance().resource(uri);
-
- //读取mapper文件
- InputStream stream = Resources.getResourceAsStream(uri);
-
- //mapper映射文件都是通过XMLMapperBuilder解析
- XMLMapperBuilder mapperParser = new XMLMapperBuilder(stream, getConfiguration(), uri, getConfiguration().getSqlFragments());
- mapperParser.parse();
- } catch (Exception e) {
- throw new RuntimeException(e);
- }
- }
-
- private void compatibilityTipsOfXml(String val) {
- //todo: 兼容提醒:
- //if (val.endsWith("*.xml") && val.indexOf("*") == val.indexOf("*.xml")) {
- //@Deprecated //弃用提示
- // log.warn("Mybatis-新文件表达式提示:'" + val + "' 不包括深度子目录;如有需要可增加'/**/'段");
- //}
- }
-
-
- public void mapperPublish() {
- for (Class> clz : getConfiguration().getMapperRegistry().getMappers()) {
- mapperPublishDo(clz);
- }
- }
-
- private void mapperPublishDo(Class> clz) {
- if (clz != null && clz.isInterface()) {
- Object mapper = getMapper(clz);
-
- //进入容器,用于 @Inject 注入
- dsWrap.context().wrapAndPut(clz, mapper);
- }
- }
-}
diff --git a/mybatis-flex-solon-plugin/src/main/java/com/mybatisflex/solon/mybtais/MybatisPluginUtils.java b/mybatis-flex-solon-plugin/src/main/java/com/mybatisflex/solon/mybtais/MybatisPluginUtils.java
deleted file mode 100644
index 72999635..00000000
--- a/mybatis-flex-solon-plugin/src/main/java/com/mybatisflex/solon/mybtais/MybatisPluginUtils.java
+++ /dev/null
@@ -1,60 +0,0 @@
-package com.mybatisflex.solon.mybtais;
-
-import org.apache.ibatis.plugin.Interceptor;
-import org.noear.solon.core.Props;
-import org.noear.solon.core.util.ClassUtil;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-
-/**
- * 插件解析工具
- *
- * @author noear
- * @since 1.10
- */
-public class MybatisPluginUtils {
- /**
- * 解析
- *
- * @param prefix 配置前缀
- */
- public static List resolve(Props configRoot, String prefix) {
- List interceptors = new ArrayList<>();
-
- int index = 0;
- while (true) {
- Props props = configRoot.getProp(prefix + "[" + index + "]");
- if (props.size() == 0) {
- break;
- } else {
- index++;
-
- String name = null;
- for (Map.Entry kv : props.entrySet()) {
- if (kv.getKey() instanceof String) {
- String key = (String) kv.getKey();
- if (key.endsWith(".class")) {
- name = key.split("\\.")[0];
- }
- }
- }
-
- if (name != null) {
- props = props.getProp(name);
- Interceptor plugin = ClassUtil.tryInstance(props.get("class"));
- if (plugin == null) {
- throw new IllegalArgumentException("Mybatis plugin [" + name + "].class load failed");
- }
- props.remove("class");
-
- plugin.setProperties(props);
- interceptors.add(plugin);
- }
- }
- }
-
- return interceptors;
- }
-}
diff --git a/mybatis-flex-solon-plugin/src/main/java/com/mybatisflex/solon/mybtais/MybatisMapperInterceptor.java b/mybatis-flex-solon-plugin/src/main/java/com/mybatisflex/solon/transaction/MybatisMapperInterceptor.java
similarity index 95%
rename from mybatis-flex-solon-plugin/src/main/java/com/mybatisflex/solon/mybtais/MybatisMapperInterceptor.java
rename to mybatis-flex-solon-plugin/src/main/java/com/mybatisflex/solon/transaction/MybatisMapperInterceptor.java
index 1daad1cb..c2eaf868 100644
--- a/mybatis-flex-solon-plugin/src/main/java/com/mybatisflex/solon/mybtais/MybatisMapperInterceptor.java
+++ b/mybatis-flex-solon-plugin/src/main/java/com/mybatisflex/solon/transaction/MybatisMapperInterceptor.java
@@ -1,4 +1,4 @@
-package com.mybatisflex.solon.mybtais;
+package com.mybatisflex.solon.transaction;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
diff --git a/mybatis-flex-solon-plugin/src/main/java/com/mybatisflex/solon/mybtais/SolonManagedTransaction.java b/mybatis-flex-solon-plugin/src/main/java/com/mybatisflex/solon/transaction/SolonManagedTransaction.java
similarity index 97%
rename from mybatis-flex-solon-plugin/src/main/java/com/mybatisflex/solon/mybtais/SolonManagedTransaction.java
rename to mybatis-flex-solon-plugin/src/main/java/com/mybatisflex/solon/transaction/SolonManagedTransaction.java
index ba41edc0..84574b5e 100644
--- a/mybatis-flex-solon-plugin/src/main/java/com/mybatisflex/solon/mybtais/SolonManagedTransaction.java
+++ b/mybatis-flex-solon-plugin/src/main/java/com/mybatisflex/solon/transaction/SolonManagedTransaction.java
@@ -1,4 +1,4 @@
-package com.mybatisflex.solon.mybtais;
+package com.mybatisflex.solon.transaction;
import com.mybatisflex.core.datasource.FlexDataSourceRouting;
import org.apache.ibatis.transaction.Transaction;
diff --git a/mybatis-flex-solon-plugin/src/main/java/com/mybatisflex/solon/mybtais/SolonManagedTransactionFactory.java b/mybatis-flex-solon-plugin/src/main/java/com/mybatisflex/solon/transaction/SolonManagedTransactionFactory.java
similarity index 95%
rename from mybatis-flex-solon-plugin/src/main/java/com/mybatisflex/solon/mybtais/SolonManagedTransactionFactory.java
rename to mybatis-flex-solon-plugin/src/main/java/com/mybatisflex/solon/transaction/SolonManagedTransactionFactory.java
index 6a37b3c9..aa6d6756 100644
--- a/mybatis-flex-solon-plugin/src/main/java/com/mybatisflex/solon/mybtais/SolonManagedTransactionFactory.java
+++ b/mybatis-flex-solon-plugin/src/main/java/com/mybatisflex/solon/transaction/SolonManagedTransactionFactory.java
@@ -1,4 +1,4 @@
-package com.mybatisflex.solon.mybtais;
+package com.mybatisflex.solon.transaction;
import org.apache.ibatis.session.TransactionIsolationLevel;
import org.apache.ibatis.transaction.Transaction;
diff --git a/mybatis-flex-solon-plugin/src/main/resources/META-INF/solon/mybatis-flex-solon-plugin.properties b/mybatis-flex-solon-plugin/src/main/resources/META-INF/solon/mybatis-flex-solon-plugin.properties
index 8e22aec1..d0d4daa6 100644
--- a/mybatis-flex-solon-plugin/src/main/resources/META-INF/solon/mybatis-flex-solon-plugin.properties
+++ b/mybatis-flex-solon-plugin/src/main/resources/META-INF/solon/mybatis-flex-solon-plugin.properties
@@ -1,2 +1,2 @@
-solon.plugin=com.mybatisflex.solon.integration.XPluginImpl
-solon.plugin.priority=3
\ No newline at end of file
+solon.plugin=com.mybatisflex.solon.integration.MybatisFlexPlugin
+solon.plugin.priority=5
diff --git a/mybatis-flex-solon-plugin/src/test/java/com/mybatisflex/solon/demo/MyBatisFlexCustomizerImpl.java b/mybatis-flex-solon-plugin/src/test/java/com/mybatisflex/solon/demo/MyBatisFlexCustomizerImpl.java
new file mode 100644
index 00000000..43b2700a
--- /dev/null
+++ b/mybatis-flex-solon-plugin/src/test/java/com/mybatisflex/solon/demo/MyBatisFlexCustomizerImpl.java
@@ -0,0 +1,23 @@
+package com.mybatisflex.solon.demo;
+
+import com.mybatisflex.core.FlexGlobalConfig;
+import com.mybatisflex.core.mybatis.FlexConfiguration;
+import com.mybatisflex.solon.ConfigurationCustomizer;
+import com.mybatisflex.solon.MyBatisFlexCustomizer;
+import org.noear.solon.annotation.Component;
+
+/**
+ * @author noear 2024/12/17 created
+ */
+@Component
+public class MyBatisFlexCustomizerImpl implements MyBatisFlexCustomizer, ConfigurationCustomizer {
+ @Override
+ public void customize(FlexGlobalConfig globalConfig) {
+
+ }
+
+ @Override
+ public void customize(FlexConfiguration configuration) {
+
+ }
+}