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 - 2024 Weber Informatics LLC | Privacy Policy