mirror of
https://gitee.com/mybatis-flex/mybatis-flex.git
synced 2025-12-07 00:58:24 +08:00
237 lines
8.8 KiB
Java
237 lines
8.8 KiB
Java
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.SolonManagedTransactionFactory;
|
||
import com.mybatisflex.solon.transaction.MybatisSessionTemplate;
|
||
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 org.slf4j.Logger;
|
||
import org.slf4j.LoggerFactory;
|
||
|
||
import javax.sql.DataSource;
|
||
import java.io.InputStream;
|
||
|
||
/**
|
||
* Mybatis-Flex 自动装配
|
||
*
|
||
* @author noear 2024/12/17 created
|
||
*/
|
||
@Configuration
|
||
public class MybatisFlexAutoConfiguration {
|
||
private static final Logger LOGGER = LoggerFactory.getLogger(MybatisFlexAutoConfiguration.class);
|
||
|
||
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 FlexGlobalConfig globalConfig(MybatisFlexProperties flexProperties,
|
||
FlexConfiguration flexConfiguration,
|
||
@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);
|
||
|
||
if (flexCustomizer != null) {
|
||
flexCustomizer.customize(globalConfig);
|
||
}
|
||
|
||
//增加事件总线扩展
|
||
EventBus.publish(globalConfig);
|
||
|
||
//绑定(不能少)
|
||
FlexGlobalConfig.setConfig(flexConfiguration.getEnvironment().getId(), globalConfig, true);
|
||
|
||
return globalConfig;
|
||
}
|
||
|
||
@Bean
|
||
public SqlSessionFactory sqlSessionFactory(MybatisFlexProperties flexProperties,
|
||
FlexConfiguration flexConfiguration,
|
||
FlexGlobalConfig globalConfig,
|
||
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) {
|
||
if (LOGGER.isWarnEnabled()) {
|
||
LOGGER.warn("Property 'mapperLocations' was specified but matching resources are not found.");
|
||
}
|
||
}
|
||
}
|
||
|
||
//所有配置全准备好了(flexConfiguration、globalConfig),才能构建
|
||
return sqlSessionFactoryBuilder.build(flexConfiguration);
|
||
}
|
||
|
||
@Bean
|
||
public void mapperPublish(FlexConfiguration flexConfiguration,
|
||
FlexGlobalConfig globalConfig,
|
||
SqlSessionFactory sqlSessionFactory) {
|
||
MybatisSessionTemplate sqlSessionTemplate = new MybatisSessionTemplate(sqlSessionFactory);
|
||
|
||
for (Class<?> mapperClz : flexConfiguration.getMapperRegistry().getMappers()) {
|
||
Object mapperProxy = sqlSessionTemplate.getMapper(mapperClz);
|
||
|
||
//推入容器,之后可以被注入
|
||
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;
|
||
}
|
||
}
|
||
}
|