All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.github.jchanghong.autoconfig.SqlAutoConfiguration.kt Maven / Gradle / Ivy

package com.github.jchanghong.autoconfig

import cn.hutool.core.io.resource.ResourceUtil
import cn.hutool.core.util.StrUtil
import cn.hutool.db.DbUtil
import com.baomidou.mybatisplus.annotation.DbType
import com.github.jchanghong.autoconfig.db.mybatis.JBeanNameGenerator
import com.github.jchanghong.autoconfig.db.mybatis.JchMyBatisPlugin
import com.github.jchanghong.database.DBHelper
import com.github.jchanghong.gson.logger
import com.github.jchanghong.log.kInfo
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory
import org.springframework.beans.factory.support.BeanDefinitionRegistry
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor
import org.springframework.beans.factory.support.DefaultListableBeanFactory
import org.springframework.beans.factory.support.GenericBeanDefinition
import org.springframework.cache.interceptor.CacheAspectSupport
import org.springframework.context.ApplicationContext
import org.springframework.context.ApplicationContextAware
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.context.annotation.Import
import org.springframework.jdbc.datasource.DataSourceTransactionManager
import springfox.documentation.builders.ApiInfoBuilder
import springfox.documentation.builders.PathSelectors
import springfox.documentation.builders.RequestHandlerSelectors
import springfox.documentation.service.ApiInfo
import springfox.documentation.spi.DocumentationType
import springfox.documentation.spring.web.plugins.Docket
import springfox.documentation.swagger2.annotations.EnableSwagger2
import java.lang.reflect.Method
import java.util.*
import java.util.function.Supplier
import javax.annotation.PostConstruct
import javax.sql.DataSource

/** 库全局配置*/
object JchAutoConfig {
	var logSql = false
	var lockDB = false
	var swagger2BasePackage: String? = null
	val mybatisPlusConfigList = arrayListOf()
}

/** spring boot 自动配置mybatis plus。多数据库,在spring 容器启动前加入配置!!!*/
data class MybatisPlusConfig @JvmOverloads constructor(
	val beanName: String, val dataSource: DataSource,
	val mapperInterfacePackage: String,
	val mapperXMLLocations: String? = null,
	/** 初始化sql,class path 路径文件*/
	val initSql: String? = null,
	val dbType: DbType
)

@Target(AnnotationTarget.CLASS)
@Retention(AnnotationRetention.RUNTIME)
@MustBeDocumented
@Import(JchMyBatisPlugin::class, SqlAutoConfiguration::class)
annotation class EnableJCHAutoConfiguration

@Target(AnnotationTarget.CLASS)
@Retention(AnnotationRetention.RUNTIME)
@MustBeDocumented
@Import(JchSwaggerConfig::class)
annotation class EnableJchSwaggerConfig

@Target(AnnotationTarget.CLASS)
@Retention(AnnotationRetention.RUNTIME)
@MustBeDocumented
@Import(JchRedisCacheConfig::class)
annotation class EnableJchRedisCacheConfig


@Configuration
open class SqlAutoConfiguration : BeanDefinitionRegistryPostProcessor, ApplicationContextAware {
	override fun setApplicationContext(applicationContext: ApplicationContext) {
		kInfo("setApplicationContext${applicationContext.beanDefinitionCount}")
	}

	//    步骤3
	override fun postProcessBeanFactory(beanFactory: ConfigurableListableBeanFactory) {
		if (beanFactory is DefaultListableBeanFactory) {
			kInfo("postProcessBeanFactory${beanFactory.beanDefinitionCount}")
			if (JchAutoConfig.mybatisPlusConfigList.size > 0) {
				for (mybatisPlusConfig in JchAutoConfig.mybatisPlusConfigList) {
					if (!mybatisPlusConfig.initSql.isNullOrBlank()) {
						try {
							kInfo("执行init sql文件 ${mybatisPlusConfig.initSql}")
							val sqlList = StrUtil.splitTrim(ResourceUtil.readUtf8Str(mybatisPlusConfig.initSql), ";")
							for (sql in sqlList) {
								kotlin.runCatching {
									logger.info(sql + "\n")
									DbUtil.use(mybatisPlusConfig.dataSource).execute(sql)
								}
							}
//                            val sqlSessionFactory =
//                                    beanFactory.getBean(mybatisPlusConfig.beanName+"_sqlSessionFactory", SqlSessionFactory::class.java)
//                            sqlSessionFactory.openSession().use {
//                                val scriptRunner = ScriptRunner(it.connection)
//                                scriptRunner.setStopOnError(true)
//                                scriptRunner.runScript(ResourceUtil.getUtf8Reader(mybatisPlusConfig.initSql))
//                            }
						} catch (e: Exception) {
							logger.error(e.localizedMessage, e)
						}
					}
				}
			}
		}
		setCache(beanFactory)
	}

	private fun setCache(beanFactory: ConfigurableListableBeanFactory) {
		kotlin.runCatching {
			val map: Map = beanFactory.getBeansOfType(CacheAspectSupport::class.java)
			for ((k, v) in map) {
				v.setKeyGenerator { target: Any, method: Method, params: Array ->
					val s = if (params.isNullOrEmpty()) "" else params.joinToString(separator = "") {
						it?.javaClass?.name + Objects.hashCode(it)
					}
					"${target::class.qualifiedName}${method.name}${s}"
				}
				kInfo("设置cache ${k} setKeyGenerator")
			}
		}
	}

	// 步骤2
//    @OptIn(ExperimentalStdlibApi::class)
	override fun postProcessBeanDefinitionRegistry(registry: BeanDefinitionRegistry) {
		kInfo("postProcessBeanDefinitionRegistry${registry.beanDefinitionCount}")
		if (JchAutoConfig.mybatisPlusConfigList.size > 0) {
			kInfo("配置 AutoConfig.mybatisPlusConfigList ${JchAutoConfig.mybatisPlusConfigList.size}")
			for ((index, mybatisPlusConfig) in JchAutoConfig.mybatisPlusConfigList.withIndex()) {
				val beanName = mybatisPlusConfig.beanName
				registry.registerBeanDefinition(beanName + "_sqlSessionFactory", GenericBeanDefinition().apply {
					instanceSupplier = Supplier {
						DBHelper.getMybatisSqlSessionFactory(
							mybatisPlusConfig.dbType,
							mybatisPlusConfig.dataSource,
							mybatisPlusConfig.mapperInterfacePackage, mybatisPlusConfig.mapperXMLLocations
						)
					}
					this.isPrimary = index == 0
				})
				registry.registerBeanDefinition(beanName + "_transactionManager",
					GenericBeanDefinition().apply {
						instanceSupplier = Supplier {
							DataSourceTransactionManager(mybatisPlusConfig.dataSource)
						}
						this.isPrimary = index == 0
					})
				DBHelper.newMapperScannerConfigurer(
					mybatisPlusConfig.mapperInterfacePackage,
					beanName + "_sqlSessionFactory"
				).apply {
					nameGenerator = JBeanNameGenerator()
					postProcessBeanDefinitionRegistry(registry)
				}
			}
		}
		kInfo("postProcessBeanDefinitionRegistry${registry.beanDefinitionCount}")
	}


	@PostConstruct
	fun inited() {
		kInfo("jchanghong自动配置完成==============================")
	}
}

@Configuration
@EnableSwagger2
class JchSwaggerConfig {
	@Bean
	fun api(): Docket {
		return Docket(DocumentationType.SWAGGER_2)
			.apiInfo(apiInfo())
			.select() // 自行修改为自己的包路径
			.apis(RequestHandlerSelectors.basePackage(JchAutoConfig.swagger2BasePackage.toString()))
			.paths(PathSelectors.any())
			.build()
	}

	private fun apiInfo(): ApiInfo {
		return ApiInfoBuilder()
			.title("接口文档")
			.description("接口文档") //服务条款网址
			//.termsOfServiceUrl("http://blog.csdn.net/forezp")
			.version("1.0") //.contact(new Contact("岳阳", "url", "email"))
			.build()
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy