From 40c67468e94c0e372ab411c9a380c414567aafa7 Mon Sep 17 00:00:00 2001 From: noear Date: Tue, 17 Dec 2024 11:19:01 +0800 Subject: [PATCH] =?UTF-8?q?mybatis-flex-solon-plugin=EF=BC=9A=E6=94=B9?= =?UTF-8?q?=E4=B8=BA=20MybatisFlexAutoConfiguration=20=E5=AE=B9=E5=99=A8?= =?UTF-8?q?=E8=87=AA=E5=8A=A8=E8=A3=85=E9=85=8D=E7=9A=84=E9=A3=8E=E6=A0=BC?= =?UTF-8?q?=EF=BC=8C=E6=96=B9=E4=BE=BF=E7=86=9F=E6=82=89=20spring=20?= =?UTF-8?q?=E7=9A=84=E5=90=8C=E5=AD=A6=E9=98=85=E8=AF=BB=E5=92=8C=E7=BB=B4?= =?UTF-8?q?=E6=8A=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- mybatis-flex-solon-plugin/README.md | 27 +- .../datasource/FlexDataSourceRouting.java | 6 +- .../solon/ConfigurationCustomizer.java | 34 ++ .../solon/MyBatisFlexCustomizer.java | 48 +++ .../solon/MybatisFlexAutoConfiguration.java | 231 ++++++++++++ .../solon/MybatisFlexProperties.java | 20 +- .../annotation/UseDataSourceInterceptor.java | 35 ++ .../aot/MybatisRuntimeNativeRegistrar.java | 62 ++-- .../solon/integration/MybatisAdapterFlex.java | 170 --------- ...PluginImpl.java => MybatisFlexPlugin.java} | 166 +++------ .../solon/mybtais/MybatisAdapterDefault.java | 351 ------------------ .../solon/mybtais/MybatisPluginUtils.java | 60 --- .../MybatisMapperInterceptor.java | 2 +- .../SolonManagedTransaction.java | 2 +- .../SolonManagedTransactionFactory.java | 2 +- .../mybatis-flex-solon-plugin.properties | 4 +- .../solon/demo/MyBatisFlexCustomizerImpl.java | 23 ++ 17 files changed, 483 insertions(+), 760 deletions(-) create mode 100644 mybatis-flex-solon-plugin/src/main/java/com/mybatisflex/solon/ConfigurationCustomizer.java create mode 100644 mybatis-flex-solon-plugin/src/main/java/com/mybatisflex/solon/MyBatisFlexCustomizer.java create mode 100644 mybatis-flex-solon-plugin/src/main/java/com/mybatisflex/solon/MybatisFlexAutoConfiguration.java create mode 100644 mybatis-flex-solon-plugin/src/main/java/com/mybatisflex/solon/annotation/UseDataSourceInterceptor.java delete mode 100644 mybatis-flex-solon-plugin/src/main/java/com/mybatisflex/solon/integration/MybatisAdapterFlex.java rename mybatis-flex-solon-plugin/src/main/java/com/mybatisflex/solon/integration/{XPluginImpl.java => MybatisFlexPlugin.java} (54%) delete mode 100644 mybatis-flex-solon-plugin/src/main/java/com/mybatisflex/solon/mybtais/MybatisAdapterDefault.java delete mode 100644 mybatis-flex-solon-plugin/src/main/java/com/mybatisflex/solon/mybtais/MybatisPluginUtils.java rename mybatis-flex-solon-plugin/src/main/java/com/mybatisflex/solon/{mybtais => transaction}/MybatisMapperInterceptor.java (95%) rename mybatis-flex-solon-plugin/src/main/java/com/mybatisflex/solon/{mybtais => transaction}/SolonManagedTransaction.java (97%) rename mybatis-flex-solon-plugin/src/main/java/com/mybatisflex/solon/{mybtais => transaction}/SolonManagedTransactionFactory.java (95%) create mode 100644 mybatis-flex-solon-plugin/src/test/java/com/mybatisflex/solon/demo/MyBatisFlexCustomizerImpl.java 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 配置。 + * + *

一般可以用于去初始化: + * + *

+ */ +@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) { + + } +}