From 07684e814df28000ba84c82495e8500d8aa32266 Mon Sep 17 00:00:00 2001 From: alex Date: Thu, 18 Aug 2022 14:35:01 +0800 Subject: [PATCH] 1.1.0 add service / repository / query spring auto config function --- build.gradle | 4 +- settings.gradle | 6 +- src/gaea.app/build.gradle | 2 + .../com/synebula/gaea/app/Application.kt | 4 +- .../synebula/gaea/app/SimpleApplication.kt | 4 +- .../app/autoconfig/service/ServiceFactory.kt | 15 +++ .../app/autoconfig/service/ServiceProxy.kt | 56 +++++++++ .../app/autoconfig/service/ServiceRegister.kt | 50 ++++++++ .../app/autoconfig/service/ServiceScan.kt | 12 ++ .../com/synebula/gaea/app/query/IQueryApp.kt | 15 +-- .../com/synebula/gaea/app/query/QueryApp.kt | 3 +- src/{gaea.mongo => gaea.mongodb}/build.gradle | 1 + .../com/synebula/gaea/mongodb}/MongoExt.kt | 14 +-- .../mongodb/autoconfig/MongodbRepoFactory.kt | 15 +++ .../mongodb/autoconfig/MongodbRepoProxy.kt | 84 ++++++++++++++ .../mongodb/autoconfig/MongodbRepoRegister.kt | 54 +++++++++ .../mongodb/autoconfig/MongodbRepoScan.kt | 12 ++ .../gaea/mongodb/query/MongodbQuery.kt | 102 ++++++++++++++++ .../mongodb/query/MongodbUniversalQuery.kt} | 30 ++--- .../mongodb/repository/MongodbRepository.kt | 47 ++++++++ .../repository/MongodbUniversalRepository.kt} | 34 ++++-- src/gaea.spring/build.gradle | 22 ++++ .../gaea/spring/autoconfig/Factory.kt | 44 +++++++ .../synebula/gaea/spring/autoconfig/Proxy.kt | 43 +++++++ .../gaea/spring/autoconfig/ProxyType.kt | 3 + .../gaea/spring/autoconfig/Register.kt | 109 ++++++++++++++++++ .../gaea/domain/repository/IRepository.kt | 41 ++++--- .../domain/repository/ISpecificRepository.kt | 61 ---------- .../domain/repository/IUniversalRepository.kt | 65 +++++++++++ .../synebula/gaea/domain/service/IService.kt | 48 +++++--- .../gaea/domain/service/ISimpleService.kt | 43 ++++--- .../synebula/gaea/domain/service/Service.kt | 98 ++++++++-------- .../gaea/domain/service/ServiceDependency.kt | 16 +++ .../gaea/domain/service/SimpleService.kt | 61 ++++------ .../kotlin/com/synebula/gaea/query/IQuery.kt | 19 +-- .../{ISpecificQuery.kt => IUniversalQuery.kt} | 16 +-- .../gaea/query/{type => }/Operator.kt | 2 +- .../synebula/gaea/query/{type => }/Order.kt | 2 +- .../kotlin/com/synebula/gaea/query/Params.kt | 2 - .../gaea/query/{annotation => }/Table.kt | 2 +- .../gaea/query/{annotation => }/Where.kt | 4 +- .../kotlin/com/synebula/gaea/reflect/Types.kt | 8 +- 42 files changed, 1001 insertions(+), 272 deletions(-) create mode 100644 src/gaea.app/src/main/kotlin/com/synebula/gaea/app/autoconfig/service/ServiceFactory.kt create mode 100644 src/gaea.app/src/main/kotlin/com/synebula/gaea/app/autoconfig/service/ServiceProxy.kt create mode 100644 src/gaea.app/src/main/kotlin/com/synebula/gaea/app/autoconfig/service/ServiceRegister.kt create mode 100644 src/gaea.app/src/main/kotlin/com/synebula/gaea/app/autoconfig/service/ServiceScan.kt rename src/{gaea.mongo => gaea.mongodb}/build.gradle (87%) rename src/{gaea.mongo/src/main/kotlin/com/synebula/gaea/mongo => gaea.mongodb/src/main/kotlin/com/synebula/gaea/mongodb}/MongoExt.kt (93%) create mode 100644 src/gaea.mongodb/src/main/kotlin/com/synebula/gaea/mongodb/autoconfig/MongodbRepoFactory.kt create mode 100644 src/gaea.mongodb/src/main/kotlin/com/synebula/gaea/mongodb/autoconfig/MongodbRepoProxy.kt create mode 100644 src/gaea.mongodb/src/main/kotlin/com/synebula/gaea/mongodb/autoconfig/MongodbRepoRegister.kt create mode 100644 src/gaea.mongodb/src/main/kotlin/com/synebula/gaea/mongodb/autoconfig/MongodbRepoScan.kt create mode 100644 src/gaea.mongodb/src/main/kotlin/com/synebula/gaea/mongodb/query/MongodbQuery.kt rename src/{gaea.mongo/src/main/kotlin/com/synebula/gaea/mongo/query/MongodbQuery.kt => gaea.mongodb/src/main/kotlin/com/synebula/gaea/mongodb/query/MongodbUniversalQuery.kt} (82%) create mode 100644 src/gaea.mongodb/src/main/kotlin/com/synebula/gaea/mongodb/repository/MongodbRepository.kt rename src/{gaea.mongo/src/main/kotlin/com/synebula/gaea/mongo/repository/MongodbRepository.kt => gaea.mongodb/src/main/kotlin/com/synebula/gaea/mongodb/repository/MongodbUniversalRepository.kt} (55%) create mode 100644 src/gaea.spring/build.gradle create mode 100644 src/gaea.spring/src/main/kotlin/com/synebula/gaea/spring/autoconfig/Factory.kt create mode 100644 src/gaea.spring/src/main/kotlin/com/synebula/gaea/spring/autoconfig/Proxy.kt create mode 100644 src/gaea.spring/src/main/kotlin/com/synebula/gaea/spring/autoconfig/ProxyType.kt create mode 100644 src/gaea.spring/src/main/kotlin/com/synebula/gaea/spring/autoconfig/Register.kt delete mode 100644 src/gaea/src/main/kotlin/com/synebula/gaea/domain/repository/ISpecificRepository.kt create mode 100644 src/gaea/src/main/kotlin/com/synebula/gaea/domain/repository/IUniversalRepository.kt create mode 100644 src/gaea/src/main/kotlin/com/synebula/gaea/domain/service/ServiceDependency.kt rename src/gaea/src/main/kotlin/com/synebula/gaea/query/{ISpecificQuery.kt => IUniversalQuery.kt} (61%) rename src/gaea/src/main/kotlin/com/synebula/gaea/query/{type => }/Operator.kt (92%) rename src/gaea/src/main/kotlin/com/synebula/gaea/query/{type => }/Order.kt (84%) rename src/gaea/src/main/kotlin/com/synebula/gaea/query/{annotation => }/Table.kt (51%) rename src/gaea/src/main/kotlin/com/synebula/gaea/query/{annotation => }/Where.kt (83%) diff --git a/build.gradle b/build.gradle index 6bc8aba..1b16f91 100644 --- a/build.gradle +++ b/build.gradle @@ -1,6 +1,6 @@ buildscript { ext { - kotlin_version = '1.7.0' + kotlin_version = '1.6.10' spring_version = "2.7.0" } @@ -17,7 +17,7 @@ buildscript { subprojects { group 'com.synebula' - version '1.0.0' + version '1.1.0' buildscript { repositories { diff --git a/settings.gradle b/settings.gradle index 55f9af1..1647a40 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,4 +1,8 @@ rootProject.name = 'gaea' include 'src:gaea' include 'src:gaea.app' -include 'src:gaea.mongo' +include 'src:gaea.mongodb' +include 'src:gaea.spring' +include 'src:gaea.spring' +findProject(':src:gaea.spring')?.name = 'gaea.spring' + diff --git a/src/gaea.app/build.gradle b/src/gaea.app/build.gradle index 772fc05..9af631c 100644 --- a/src/gaea.app/build.gradle +++ b/src/gaea.app/build.gradle @@ -8,6 +8,8 @@ apply plugin: 'kotlin-spring' dependencies { api project(":src:gaea") + api project(":src:gaea.spring") + api("org.springframework.boot:spring-boot-starter-web:$spring_version") api("org.springframework.boot:spring-boot-starter-aop:$spring_version") api("org.springframework.boot:spring-boot-starter-mail:$spring_version") diff --git a/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/Application.kt b/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/Application.kt index 759905e..7e0a5c7 100644 --- a/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/Application.kt +++ b/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/Application.kt @@ -13,16 +13,14 @@ import javax.annotation.Resource * 联合服务,同时实现了ICommandApp和IQueryApp接口 * * @param name 业务名称 - * @param clazz 试图业务对象 * @param service 业务domain服务 * @param query 业务查询服务 * @param logger 日志组件 */ open class Application( override var name: String, - override var clazz: Class, override var service: IService, - override var query: IQuery, + override var query: IQuery, override var logger: ILogger, ) : ICommandApp, IQueryApp { diff --git a/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/SimpleApplication.kt b/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/SimpleApplication.kt index 1a9102b..e06f139 100644 --- a/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/SimpleApplication.kt +++ b/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/SimpleApplication.kt @@ -13,16 +13,14 @@ import javax.annotation.Resource * 简单的服务, 取消了Command对象 * * @param name 业务名称 - * @param clazz 业务对象类型 * @param service 业务domain服务 * @param query 业务查询服务 * @param logger 日志组件 */ open class SimpleApplication, ID>( override var name: String, - override var clazz: Class, override var service: ISimpleService, - override var query: IQuery, + override var query: IQuery, override var logger: ILogger, ) : ISimpleCommandApp, IQueryApp { diff --git a/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/autoconfig/service/ServiceFactory.kt b/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/autoconfig/service/ServiceFactory.kt new file mode 100644 index 0000000..e3447dd --- /dev/null +++ b/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/autoconfig/service/ServiceFactory.kt @@ -0,0 +1,15 @@ +package com.synebula.gaea.app.autoconfig.service + +import com.synebula.gaea.spring.autoconfig.Factory +import com.synebula.gaea.spring.autoconfig.Proxy +import org.springframework.beans.factory.BeanFactory + +class ServiceFactory( + supertype: Class<*>, + var beanFactory: BeanFactory, + var implementBeanNames: Array = arrayOf() +) : Factory(supertype) { + override fun createProxy(): Proxy { + return ServiceProxy(supertype, this.beanFactory, this.implementBeanNames) + } +} \ No newline at end of file diff --git a/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/autoconfig/service/ServiceProxy.kt b/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/autoconfig/service/ServiceProxy.kt new file mode 100644 index 0000000..5aa6bce --- /dev/null +++ b/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/autoconfig/service/ServiceProxy.kt @@ -0,0 +1,56 @@ +package com.synebula.gaea.app.autoconfig.service + +import com.synebula.gaea.data.serialization.IObjectMapper +import com.synebula.gaea.domain.repository.IRepository +import com.synebula.gaea.domain.service.IService +import com.synebula.gaea.domain.service.Service +import com.synebula.gaea.domain.service.ServiceDependency +import com.synebula.gaea.spring.autoconfig.Proxy +import org.springframework.beans.factory.BeanFactory +import java.io.InvalidClassException +import java.lang.reflect.Method + +class ServiceProxy( + private var supertype: Class<*>, private var beanFactory: BeanFactory, implementBeanNames: Array = arrayOf() +) : Proxy() { + + private var service: IService<*> + + init { + // 如果没有实现类, 使用Service类代理 + if (implementBeanNames.isEmpty()) { + // 如果没有实现类并且没有ServiceDependency注解, 则抛出异常 + if (!this.supertype.declaredAnnotations.any { it.annotationClass == ServiceDependency::class }) { + throw InvalidClassException( + "interface ${this.supertype.name} must has implementation class or annotation by ${ServiceDependency::class.qualifiedName}" + ) + } + val serviceDependency = this.supertype.getDeclaredAnnotation(ServiceDependency::class.java) + val repo = this.beanFactory.getBean(serviceDependency.repo.java) + val mapper = this.beanFactory.getBean(IObjectMapper::class.java) + val constructor = Service::class.java.getConstructor( + Class::class.java, IRepository::class.java, IObjectMapper::class.java + ) + this.service = constructor.newInstance(serviceDependency.clazz.java, repo, mapper) + } else { + this.service = this.beanFactory.getBean(implementBeanNames[0]) as IService<*> + } + } + + /** + * 执行代理方法 + * + * @param proxy 代理对象 + * @param method 需要执行的方法 + * @param args 参数列表 + * @return 方法执行结果 + */ + override fun exec(proxy: Any, method: Method, args: Array): Any? { + try { + val proxyMethod = this.service.javaClass.getDeclaredMethod(method.name, *method.parameterTypes) + return proxyMethod.invoke(this.service, *args) + } catch (ex: NoSuchMethodException) { + throw NoSuchMethodException("method [${method.toGenericString()}] not implements in class [${this.service::class.java}], you must implements interface [${this.supertype.name}] ") + } + } +} \ No newline at end of file diff --git a/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/autoconfig/service/ServiceRegister.kt b/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/autoconfig/service/ServiceRegister.kt new file mode 100644 index 0000000..d62878b --- /dev/null +++ b/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/autoconfig/service/ServiceRegister.kt @@ -0,0 +1,50 @@ +package com.synebula.gaea.app.autoconfig.service + +import com.synebula.gaea.domain.service.IService +import com.synebula.gaea.spring.autoconfig.Register +import org.springframework.beans.factory.config.BeanDefinition +import org.springframework.beans.factory.support.BeanDefinitionBuilder +import org.springframework.beans.factory.support.GenericBeanDefinition +import org.springframework.core.annotation.AnnotationAttributes +import org.springframework.core.type.AnnotationMetadata + +class ServiceRegister : Register() { + override fun scan(metadata: AnnotationMetadata): Map { + val result = mutableMapOf() + + // 获取注解参数信息:basePackages + val attributes = AnnotationAttributes( + metadata.getAnnotationAttributes( + ServiceScan::class.java.name + ) ?: mapOf() + ) + val basePackages = attributes.getStringArray("basePackages") + val beanDefinitions = this.doScan(basePackages, arrayOf(this.interfaceFilter(arrayOf(IService::class.java)))) + beanDefinitions.forEach { beanDefinition -> + // 获取实际的bean类型 + val beanClazz: Class<*> = try { + Class.forName(beanDefinition.beanClassName) + } catch (e: ClassNotFoundException) { + throw e + } + + // 尝试获取实际继承类型 + val implBeanDefinitions = this.doScan(basePackages, arrayOf(this.interfaceFilter(arrayOf(beanClazz)))) + implBeanDefinitions.forEach { + it.isAutowireCandidate = false + result[it.beanClassName!!] = it + } + + // 构造BeanDefinition + val builder = BeanDefinitionBuilder.genericBeanDefinition(beanClazz) + builder.addConstructorArgValue(beanClazz) + builder.addConstructorArgValue(this._beanFactory) + builder.addConstructorArgValue(implBeanDefinitions.map { it.beanClassName }) + val definition = builder.rawBeanDefinition as GenericBeanDefinition + definition.beanClass = ServiceFactory::class.java + definition.autowireMode = GenericBeanDefinition.AUTOWIRE_BY_TYPE + result[beanClazz.name] = definition + } + return result + } +} \ No newline at end of file diff --git a/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/autoconfig/service/ServiceScan.kt b/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/autoconfig/service/ServiceScan.kt new file mode 100644 index 0000000..a988ac2 --- /dev/null +++ b/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/autoconfig/service/ServiceScan.kt @@ -0,0 +1,12 @@ +package com.synebula.gaea.app.autoconfig.service + +import org.springframework.context.annotation.Import +import java.lang.annotation.Inherited + + +@Target(AnnotationTarget.ANNOTATION_CLASS, AnnotationTarget.CLASS) +@Retention(AnnotationRetention.RUNTIME) +@MustBeDocumented +@Inherited +@Import(ServiceRegister::class) +annotation class ServiceScan(val basePackages: Array = []) \ No newline at end of file diff --git a/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/query/IQueryApp.kt b/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/query/IQueryApp.kt index f6f0865..e06f38f 100644 --- a/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/query/IQueryApp.kt +++ b/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/query/IQueryApp.kt @@ -13,17 +13,12 @@ interface IQueryApp : IApplication { /** * 查询服务 */ - var query: IQuery - - /** - * 查询的View类型 - */ - var clazz: Class + var query: IQuery @Method("获取数据") @GetMapping("/{id:.+}") fun get(@PathVariable id: ID): HttpMessage { - val data = this.query.get(id, clazz) + val data = this.query.get(id) val msg = HttpMessage() msg.data = data return msg @@ -32,19 +27,19 @@ interface IQueryApp : IApplication { @Method("获取列表数据") @GetMapping fun list(@RequestParam params: LinkedHashMap): HttpMessage { - val data = this.query.list(params, clazz) + val data = this.query.list(params) return HttpMessage(data) } @Method("获取分页数据") - @GetMapping("/segments/{size}/pages/{page}") + @GetMapping("/size/{size}/pages/{page}") fun paging( @PathVariable size: Int, @PathVariable page: Int, @RequestParam parameters: LinkedHashMap ): HttpMessage { val params = Params(page, size, parameters) - val data = this.query.paging(params, clazz) + val data = this.query.paging(params) return HttpMessage(data) } } \ No newline at end of file diff --git a/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/query/QueryApp.kt b/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/query/QueryApp.kt index 729f48c..a301a17 100644 --- a/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/query/QueryApp.kt +++ b/src/gaea.app/src/main/kotlin/com/synebula/gaea/app/query/QueryApp.kt @@ -12,7 +12,6 @@ import com.synebula.gaea.query.IQuery */ open class QueryApp( override var name: String, - override var clazz: Class, - override var query: IQuery, + override var query: IQuery, override var logger: ILogger, ) : IQueryApp \ No newline at end of file diff --git a/src/gaea.mongo/build.gradle b/src/gaea.mongodb/build.gradle similarity index 87% rename from src/gaea.mongo/build.gradle rename to src/gaea.mongodb/build.gradle index 41f2957..b99693a 100644 --- a/src/gaea.mongo/build.gradle +++ b/src/gaea.mongodb/build.gradle @@ -1,5 +1,6 @@ dependencies { api project(":src:gaea") + api project(":src:gaea.spring") api("org.springframework.boot:spring-boot-starter-data-mongodb:$spring_version") } diff --git a/src/gaea.mongo/src/main/kotlin/com/synebula/gaea/mongo/MongoExt.kt b/src/gaea.mongodb/src/main/kotlin/com/synebula/gaea/mongodb/MongoExt.kt similarity index 93% rename from src/gaea.mongo/src/main/kotlin/com/synebula/gaea/mongo/MongoExt.kt rename to src/gaea.mongodb/src/main/kotlin/com/synebula/gaea/mongodb/MongoExt.kt index ecf65cd..e8f57a2 100644 --- a/src/gaea.mongo/src/main/kotlin/com/synebula/gaea/mongo/MongoExt.kt +++ b/src/gaea.mongodb/src/main/kotlin/com/synebula/gaea/mongodb/MongoExt.kt @@ -1,9 +1,9 @@ -package com.synebula.gaea.mongo +package com.synebula.gaea.mongodb import com.synebula.gaea.data.date.DateTime -import com.synebula.gaea.query.annotation.Where -import com.synebula.gaea.query.type.Operator -import com.synebula.gaea.query.type.Order +import com.synebula.gaea.query.Operator +import com.synebula.gaea.query.Order +import com.synebula.gaea.query.Where import org.springframework.data.domain.Sort import org.springframework.data.mongodb.core.query.Criteria import org.springframework.data.mongodb.core.query.Query @@ -30,9 +30,9 @@ fun Query.select(fields: Array): Query { * @param onWhere 获取字段查询方式的方法 */ fun Query.where( - params: Map?, - onWhere: ((v: String) -> Where?) = { null }, - onFieldType: ((v: String) -> Class<*>?) = { null } + params: Map?, + onWhere: ((v: String) -> Where?) = { null }, + onFieldType: ((v: String) -> Class<*>?) = { null } ): Query { val list = arrayListOf() if (params != null) { diff --git a/src/gaea.mongodb/src/main/kotlin/com/synebula/gaea/mongodb/autoconfig/MongodbRepoFactory.kt b/src/gaea.mongodb/src/main/kotlin/com/synebula/gaea/mongodb/autoconfig/MongodbRepoFactory.kt new file mode 100644 index 0000000..dbdeacf --- /dev/null +++ b/src/gaea.mongodb/src/main/kotlin/com/synebula/gaea/mongodb/autoconfig/MongodbRepoFactory.kt @@ -0,0 +1,15 @@ +package com.synebula.gaea.mongodb.autoconfig + +import com.synebula.gaea.spring.autoconfig.Factory +import com.synebula.gaea.spring.autoconfig.Proxy +import org.springframework.beans.factory.BeanFactory + +class MongodbRepoFactory( + supertype: Class<*>, + var beanFactory: BeanFactory, + var implementBeanNames: Array = arrayOf() +) : Factory(supertype) { + override fun createProxy(): Proxy { + return MongodbRepoProxy(supertype, this.beanFactory, this.implementBeanNames) + } +} \ No newline at end of file diff --git a/src/gaea.mongodb/src/main/kotlin/com/synebula/gaea/mongodb/autoconfig/MongodbRepoProxy.kt b/src/gaea.mongodb/src/main/kotlin/com/synebula/gaea/mongodb/autoconfig/MongodbRepoProxy.kt new file mode 100644 index 0000000..b4eb4a8 --- /dev/null +++ b/src/gaea.mongodb/src/main/kotlin/com/synebula/gaea/mongodb/autoconfig/MongodbRepoProxy.kt @@ -0,0 +1,84 @@ +package com.synebula.gaea.mongodb.autoconfig + +import com.synebula.gaea.domain.repository.IRepository +import com.synebula.gaea.log.ILogger +import com.synebula.gaea.mongodb.query.MongodbQuery +import com.synebula.gaea.mongodb.repository.MongodbRepository +import com.synebula.gaea.query.IQuery +import com.synebula.gaea.spring.autoconfig.Proxy +import org.springframework.beans.factory.BeanFactory +import org.springframework.data.mongodb.core.MongoTemplate +import java.io.InvalidClassException +import java.lang.reflect.Method +import java.lang.reflect.ParameterizedType + +class MongodbRepoProxy( + private var supertype: Class<*>, private var beanFactory: BeanFactory, implementBeanNames: Array = arrayOf() +) : Proxy() { + + private var repo: IRepository<*, *>? = null + + private var query: IQuery<*, *>? = null + + init { + if (this.supertype.interfaces.any { it == IRepository::class.java }) { + // 如果是IRepository子接口 + if (implementBeanNames.isEmpty()) { + val genericInterfaces = this.supertype.genericInterfaces.find { + it.typeName.startsWith(IRepository::class.java.typeName) + }!! + val constructor = MongodbRepository::class.java.getConstructor( + Class::class.java, MongoTemplate::class.java + ) + this.repo = constructor.newInstance( + (genericInterfaces as ParameterizedType).actualTypeArguments[0], + this.beanFactory.getBean(MongoTemplate::class.java) + ) + } else { + this.repo = this.beanFactory.getBean(implementBeanNames[0]) as IRepository<*, *> + } + } else { + // 否则是IQuery子接口 + if (implementBeanNames.isEmpty()) { + val genericInterfaces = this.supertype.genericInterfaces.find { + it.typeName.startsWith(IQuery::class.java.typeName) + }!! + val constructor = MongodbQuery::class.java.getConstructor( + Class::class.java, MongoTemplate::class.java, ILogger::class.java + ) + this.query = constructor.newInstance( + (genericInterfaces as ParameterizedType).actualTypeArguments[0], + this.beanFactory.getBean(MongoTemplate::class.java), + this.beanFactory.getBean(ILogger::class.java), + ) + } else { + this.query = this.beanFactory.getBean(implementBeanNames[0]) as IQuery<*, *> + } + } + } + + /** + * 执行代理方法 + * + * @param proxy 代理对象 + * @param method 需要执行的方法 + * @param args 参数列表 + * @return 方法执行结果 + */ + override fun exec(proxy: Any, method: Method, args: Array): Any? { + val proxyClazz = if (this.repo != null) { + this.repo!!.javaClass + } else if (this.query != null) { + this.query!!.javaClass + } else + throw InvalidClassException("class ${this.supertype.name} property repo and query are both null") + + try { + val proxyMethod: Method = proxyClazz.getDeclaredMethod(method.name, *method.parameterTypes) + return proxyMethod.invoke(this.repo, *args) + } catch (ex: NoSuchMethodException) { + throw NoSuchMethodException("method [${method.toGenericString()}] not implements in class [${proxyClazz}], you must implements interface [${this.supertype.name}] ") + } + } + +} \ No newline at end of file diff --git a/src/gaea.mongodb/src/main/kotlin/com/synebula/gaea/mongodb/autoconfig/MongodbRepoRegister.kt b/src/gaea.mongodb/src/main/kotlin/com/synebula/gaea/mongodb/autoconfig/MongodbRepoRegister.kt new file mode 100644 index 0000000..f62cf4c --- /dev/null +++ b/src/gaea.mongodb/src/main/kotlin/com/synebula/gaea/mongodb/autoconfig/MongodbRepoRegister.kt @@ -0,0 +1,54 @@ +package com.synebula.gaea.mongodb.autoconfig + +import com.synebula.gaea.domain.repository.IRepository +import com.synebula.gaea.query.IQuery +import com.synebula.gaea.spring.autoconfig.Register +import org.springframework.beans.factory.config.BeanDefinition +import org.springframework.beans.factory.support.BeanDefinitionBuilder +import org.springframework.beans.factory.support.GenericBeanDefinition +import org.springframework.core.annotation.AnnotationAttributes +import org.springframework.core.type.AnnotationMetadata + +class MongodbRepoRegister : Register() { + override fun scan(metadata: AnnotationMetadata): Map { + val result = mutableMapOf() + + // 获取注解参数信息:basePackages + val attributes = AnnotationAttributes( + metadata.getAnnotationAttributes( + MongodbRepoScan::class.java.name + ) ?: mapOf() + ) + val basePackages = attributes.getStringArray("basePackages") + val beanDefinitions = this.doScan( + basePackages, + arrayOf(this.interfaceFilter(arrayOf(IRepository::class.java, IQuery::class.java))) + ) + beanDefinitions.forEach { beanDefinition -> + // 获取实际的bean类型 + val beanClazz: Class<*> = try { + Class.forName(beanDefinition.beanClassName) + } catch (ex: ClassNotFoundException) { + throw ex + } + + // 尝试获取实际继承类型 + val implBeanDefinitions = this.doScan(basePackages, arrayOf(this.interfaceFilter(arrayOf(beanClazz)))) + implBeanDefinitions.forEach { + it.isAutowireCandidate = false + result[it.beanClassName!!] = it + } + + // 构造BeanDefinition + val builder = BeanDefinitionBuilder.genericBeanDefinition(beanClazz) + builder.addConstructorArgValue(beanClazz) + builder.addConstructorArgValue(this._beanFactory) + builder.addConstructorArgValue(implBeanDefinitions.map { it.beanClassName }) + val definition = builder.rawBeanDefinition as GenericBeanDefinition + definition.beanClass = MongodbRepoFactory::class.java + definition.autowireMode = GenericBeanDefinition.AUTOWIRE_BY_TYPE + result[beanClazz.name] = definition + } + return result + } +} \ No newline at end of file diff --git a/src/gaea.mongodb/src/main/kotlin/com/synebula/gaea/mongodb/autoconfig/MongodbRepoScan.kt b/src/gaea.mongodb/src/main/kotlin/com/synebula/gaea/mongodb/autoconfig/MongodbRepoScan.kt new file mode 100644 index 0000000..ef8aa03 --- /dev/null +++ b/src/gaea.mongodb/src/main/kotlin/com/synebula/gaea/mongodb/autoconfig/MongodbRepoScan.kt @@ -0,0 +1,12 @@ +package com.synebula.gaea.mongodb.autoconfig + +import org.springframework.context.annotation.Import +import java.lang.annotation.Inherited + + +@Target(AnnotationTarget.ANNOTATION_CLASS, AnnotationTarget.CLASS) +@Retention(AnnotationRetention.RUNTIME) +@MustBeDocumented +@Inherited +@Import(MongodbRepoRegister::class) +annotation class MongodbRepoScan(val basePackages: Array = []) \ No newline at end of file diff --git a/src/gaea.mongodb/src/main/kotlin/com/synebula/gaea/mongodb/query/MongodbQuery.kt b/src/gaea.mongodb/src/main/kotlin/com/synebula/gaea/mongodb/query/MongodbQuery.kt new file mode 100644 index 0000000..93bff5b --- /dev/null +++ b/src/gaea.mongodb/src/main/kotlin/com/synebula/gaea/mongodb/query/MongodbQuery.kt @@ -0,0 +1,102 @@ +package com.synebula.gaea.mongodb.query + +import com.synebula.gaea.ext.fieldNames +import com.synebula.gaea.ext.firstCharLowerCase +import com.synebula.gaea.log.ILogger +import com.synebula.gaea.mongodb.order +import com.synebula.gaea.mongodb.select +import com.synebula.gaea.mongodb.where +import com.synebula.gaea.mongodb.whereId +import com.synebula.gaea.query.IQuery +import com.synebula.gaea.query.Page +import com.synebula.gaea.query.Params +import com.synebula.gaea.query.Table +import org.springframework.data.mongodb.core.MongoTemplate +import org.springframework.data.mongodb.core.query.Criteria +import org.springframework.data.mongodb.core.query.Query + +/** + * 实现IQuery的Mongodb查询类 + * @param template MongodbRepo对象 + */ + +open class MongodbQuery(override var clazz: Class, var template: MongoTemplate, var logger: ILogger) : + IQuery { + + /** + * 使用View解析是collection时是否校验存在,默认不校验 + */ + var validViewCollection = false + + override fun get(id: ID): TView? { + return this.template.findOne(whereId(id), clazz, this.collection(clazz)) + } + + override fun list(params: Map?): List { + val fields = this.fields(clazz) + val query = Query() + query.where(params, clazz) + query.select(fields) + return this.find(query, clazz) + } + + override fun count(params: Map?): Int { + val query = Query() + return this.template.count(query.where(params, clazz), this.collection(clazz)).toInt() + } + + override fun paging(params: Params): Page { + val query = Query() + val fields = this.fields(clazz) + val result = Page(params.page, params.size) + result.total = this.count(params.parameters) + //如果总数和索引相同,说明该页没有数据,直接跳到上一页 + if (result.total == result.index) { + params.page -= 1 + result.page -= 1 + } + query.select(fields) + query.where(params.parameters, clazz) + query.with(order(params.orders)) + query.skip(params.index).limit(params.size) + result.data = this.find(query, clazz) + return result + } + + override fun range(field: String, params: List): List { + return this.find(Query.query(Criteria.where(field).`in`(params)), clazz) + } + + protected fun find(query: Query, clazz: Class): List { + return this.template.find(query, clazz, this.collection(clazz)) + } + + protected fun fields(clazz: Class): Array { + val fields = mutableListOf() + fields.addAll(clazz.fieldNames()) + var parent = clazz.superclass + while (parent != Any::class.java) { + fields.addAll(clazz.superclass.fieldNames()) + parent = parent.superclass + } + return fields.toTypedArray() + } + + /** + * 获取collection + */ + protected fun collection(clazz: Class): String { + val table: Table? = clazz.getDeclaredAnnotation( + Table::class.java + ) + return if (table != null) return table.name + else { + this.logger.info(this, "视图类没有标记[Collection]注解,无法获取Collection名称。尝试使用View<${clazz.name}>名称解析集合") + val name = clazz.simpleName.removeSuffix("View").firstCharLowerCase() + if (!validViewCollection || this.template.collectionExists(name)) name + else { + throw RuntimeException("找不到名为[${clazz.name}]的集合") + } + } + } +} diff --git a/src/gaea.mongo/src/main/kotlin/com/synebula/gaea/mongo/query/MongodbQuery.kt b/src/gaea.mongodb/src/main/kotlin/com/synebula/gaea/mongodb/query/MongodbUniversalQuery.kt similarity index 82% rename from src/gaea.mongo/src/main/kotlin/com/synebula/gaea/mongo/query/MongodbQuery.kt rename to src/gaea.mongodb/src/main/kotlin/com/synebula/gaea/mongodb/query/MongodbUniversalQuery.kt index fe117cb..f88dfbc 100644 --- a/src/gaea.mongo/src/main/kotlin/com/synebula/gaea/mongo/query/MongodbQuery.kt +++ b/src/gaea.mongodb/src/main/kotlin/com/synebula/gaea/mongodb/query/MongodbUniversalQuery.kt @@ -1,16 +1,17 @@ -package com.synebula.gaea.mongo.query +package com.synebula.gaea.mongodb.query + import com.synebula.gaea.ext.fieldNames import com.synebula.gaea.ext.firstCharLowerCase import com.synebula.gaea.log.ILogger -import com.synebula.gaea.mongo.order -import com.synebula.gaea.mongo.select -import com.synebula.gaea.mongo.where -import com.synebula.gaea.mongo.whereId -import com.synebula.gaea.query.IQuery +import com.synebula.gaea.mongodb.order +import com.synebula.gaea.mongodb.select +import com.synebula.gaea.mongodb.where +import com.synebula.gaea.mongodb.whereId +import com.synebula.gaea.query.IUniversalQuery import com.synebula.gaea.query.Page import com.synebula.gaea.query.Params -import com.synebula.gaea.query.annotation.Table +import com.synebula.gaea.query.Table import org.springframework.data.mongodb.core.MongoTemplate import org.springframework.data.mongodb.core.query.Criteria import org.springframework.data.mongodb.core.query.Query @@ -19,8 +20,7 @@ import org.springframework.data.mongodb.core.query.Query * 实现IQuery的Mongodb查询类 * @param template MongodbRepo对象 */ - -open class MongodbQuery(var template: MongoTemplate, var logger: ILogger) : IQuery { +open class MongodbUniversalQuery(var template: MongoTemplate, var logger: ILogger) : IUniversalQuery { /** * 使用View解析是collection时是否校验存在,默认不校验 @@ -36,7 +36,7 @@ open class MongodbQuery(var template: MongoTemplate, var logger: ILogger) : IQue val query = Query() query.where(params, clazz) query.select(fields) - return this.template.find(query, clazz, this.collection(clazz)) + return this.find(query, clazz) } override fun count(params: Map?, clazz: Class): Int { @@ -58,12 +58,16 @@ open class MongodbQuery(var template: MongoTemplate, var logger: ILogger) : IQue query.where(params.parameters, clazz) query.with(order(params.orders)) query.skip(params.index).limit(params.size) - result.data = this.template.find(query, clazz, this.collection(clazz)) + result.data = this.find(query, clazz) return result } override fun range(field: String, params: List, clazz: Class): List { - return this.template.find(Query.query(Criteria.where(field).`in`(params)), clazz, this.collection(clazz)) + return this.find(Query.query(Criteria.where(field).`in`(params)), clazz) + } + + protected fun find(query: Query, clazz: Class): List { + return this.template.find(query, clazz, this.collection(clazz)) } fun fields(clazz: Class): Array { @@ -82,7 +86,7 @@ open class MongodbQuery(var template: MongoTemplate, var logger: ILogger) : IQue */ fun collection(clazz: Class): String { val table: Table? = clazz.getDeclaredAnnotation( - Table::class.java + Table::class.java ) return if (table != null) return table.name diff --git a/src/gaea.mongodb/src/main/kotlin/com/synebula/gaea/mongodb/repository/MongodbRepository.kt b/src/gaea.mongodb/src/main/kotlin/com/synebula/gaea/mongodb/repository/MongodbRepository.kt new file mode 100644 index 0000000..8c3a348 --- /dev/null +++ b/src/gaea.mongodb/src/main/kotlin/com/synebula/gaea/mongodb/repository/MongodbRepository.kt @@ -0,0 +1,47 @@ +package com.synebula.gaea.mongodb.repository + +import com.synebula.gaea.domain.model.IAggregateRoot +import com.synebula.gaea.domain.repository.IRepository +import com.synebula.gaea.mongodb.where +import com.synebula.gaea.mongodb.whereId +import org.springframework.data.mongodb.core.MongoTemplate +import org.springframework.data.mongodb.core.query.Query + +/** + * 实现[IRepository]的Mongodb仓储类 + * @param repo MongodbRepo对象 + */ +open class MongodbRepository, ID>( + override var clazz: Class, + protected var repo: MongoTemplate +) : IRepository { + + override fun add(obj: TAggregateRoot) { + this.repo.save(obj) + } + + override fun add(list: List) { + this.repo.insert(list, clazz) + } + + override fun remove(id: ID) { + this.repo.remove(whereId(id), clazz) + } + + override fun get(id: ID): TAggregateRoot? { + return this.repo.findOne(whereId(id), clazz) + } + + override fun update(obj: TAggregateRoot) { + this.repo.save(obj) + } + + override fun update(list: List) { + this.repo.save(list) + } + + override fun count(params: Map?): Int { + val query = Query() + return this.repo.count(query.where(params, clazz), clazz).toInt() + } +} diff --git a/src/gaea.mongo/src/main/kotlin/com/synebula/gaea/mongo/repository/MongodbRepository.kt b/src/gaea.mongodb/src/main/kotlin/com/synebula/gaea/mongodb/repository/MongodbUniversalRepository.kt similarity index 55% rename from src/gaea.mongo/src/main/kotlin/com/synebula/gaea/mongo/repository/MongodbRepository.kt rename to src/gaea.mongodb/src/main/kotlin/com/synebula/gaea/mongodb/repository/MongodbUniversalRepository.kt index 4c2b469..93a3d87 100644 --- a/src/gaea.mongo/src/main/kotlin/com/synebula/gaea/mongo/repository/MongodbRepository.kt +++ b/src/gaea.mongodb/src/main/kotlin/com/synebula/gaea/mongodb/repository/MongodbUniversalRepository.kt @@ -1,9 +1,9 @@ -package com.synebula.gaea.mongo.repository +package com.synebula.gaea.mongodb.repository import com.synebula.gaea.domain.model.IAggregateRoot -import com.synebula.gaea.domain.repository.IRepository -import com.synebula.gaea.mongo.where -import com.synebula.gaea.mongo.whereId +import com.synebula.gaea.domain.repository.IUniversalRepository +import com.synebula.gaea.mongodb.where +import com.synebula.gaea.mongodb.whereId import org.springframework.data.mongodb.core.MongoTemplate import org.springframework.data.mongodb.core.query.Query @@ -11,7 +11,7 @@ import org.springframework.data.mongodb.core.query.Query * 实现ITypedRepository的Mongodb仓储类 * @param repo MongodbRepo对象 */ -open class MongodbRepository(private var repo: MongoTemplate) : IRepository { +open class MongodbUniversalRepository(private var repo: MongoTemplate) : IUniversalRepository { override fun , ID> remove(id: ID, clazz: Class) { this.repo.remove(whereId(id), clazz) @@ -25,21 +25,33 @@ open class MongodbRepository(private var repo: MongoTemplate) : IRepository { } override fun , ID> update( - obj: TAggregateRoot, + root: TAggregateRoot, clazz: Class, ) { - this.repo.save(obj) + this.repo.save(root) } - override fun , ID> add(obj: TAggregateRoot, clazz: Class) { - this.repo.save(obj) + /** + * 更新多个个对象。 + * + * @param roots 需要更新的对象。 + */ + override fun , ID> update( + roots: List, + clazz: Class + ) { + this.repo.save(roots) + } + + override fun , ID> add(root: TAggregateRoot, clazz: Class) { + this.repo.save(root) } override fun , ID> add( - obj: List, + roots: List, clazz: Class, ) { - this.repo.insert(obj, clazz) + this.repo.insert(roots, clazz) } override fun count(params: Map?, clazz: Class): Int { diff --git a/src/gaea.spring/build.gradle b/src/gaea.spring/build.gradle new file mode 100644 index 0000000..95e297c --- /dev/null +++ b/src/gaea.spring/build.gradle @@ -0,0 +1,22 @@ +buildscript { + dependencies { + classpath("org.jetbrains.kotlin:kotlin-allopen:$kotlin_version") + } +} + +apply plugin: 'kotlin-spring' + +dependencies { + implementation project(":src:gaea") + implementation("org.springframework.boot:spring-boot-starter-web:$spring_version") + implementation group: 'com.google.code.gson', name: 'gson', version: '2.8.6' +} + +publishing { + publications { + publish(MavenPublication) { + from components.java + } + } +} + diff --git a/src/gaea.spring/src/main/kotlin/com/synebula/gaea/spring/autoconfig/Factory.kt b/src/gaea.spring/src/main/kotlin/com/synebula/gaea/spring/autoconfig/Factory.kt new file mode 100644 index 0000000..2c399a1 --- /dev/null +++ b/src/gaea.spring/src/main/kotlin/com/synebula/gaea/spring/autoconfig/Factory.kt @@ -0,0 +1,44 @@ +package com.synebula.gaea.spring.autoconfig + +import org.springframework.beans.factory.FactoryBean +import org.springframework.cglib.proxy.Enhancer +import java.lang.reflect.Proxy as JdkProxy + +/** + * 代理生成工厂 + * + * @param supertype 需要被代理的父类型 + * @param proxyType 代理类型:JDK 或 CGLIB + */ +abstract class Factory( + protected val supertype: Class<*>, + protected val proxyType: ProxyType = ProxyType.Cglib +) : FactoryBean { + override fun getObject(): Any { + val handler: Proxy = this.createProxy() + + //JDK 方式代理代码, 暂时选用cglib + val proxy: Any = if (proxyType == ProxyType.JDK) { + JdkProxy.newProxyInstance( + this.supertype.classLoader, arrayOf(this.supertype), handler + ) + } else { //cglib代理 + val enhancer = Enhancer() + enhancer.setSuperclass(supertype) + enhancer.setCallback(handler) + enhancer.create() + } + + return proxy + } + + override fun getObjectType(): Class<*> { + return supertype + } + + override fun isSingleton(): Boolean { + return true + } + + abstract fun createProxy(): Proxy +} \ No newline at end of file diff --git a/src/gaea.spring/src/main/kotlin/com/synebula/gaea/spring/autoconfig/Proxy.kt b/src/gaea.spring/src/main/kotlin/com/synebula/gaea/spring/autoconfig/Proxy.kt new file mode 100644 index 0000000..201ba8a --- /dev/null +++ b/src/gaea.spring/src/main/kotlin/com/synebula/gaea/spring/autoconfig/Proxy.kt @@ -0,0 +1,43 @@ +package com.synebula.gaea.spring.autoconfig + +import org.springframework.cglib.proxy.MethodInterceptor +import org.springframework.cglib.proxy.MethodProxy +import java.lang.reflect.InvocationHandler +import java.lang.reflect.Method + +abstract class Proxy : MethodInterceptor, InvocationHandler { + + /** + * JDK 方式代理代码 + */ + @Throws(Throwable::class) + override fun invoke(proxy: Any, method: Method, args: Array): Any? { + return if (Any::class.java == method.declaringClass) { + method.invoke(this, *args) + } else { + exec(proxy, method, args) + } + } + + /** + * 暂时选用cglib 方式代理代码 + */ + @Throws(Throwable::class) + override fun intercept(proxy: Any, method: Method, args: Array, methodProxy: MethodProxy): Any? { + return if (Any::class.java == method.declaringClass) { + methodProxy.invoke(this, args) + } else { + exec(proxy, method, args) + } + } + + /** + * 执行代理方法 + * + * @param proxy 代理对象 + * @param method 需要执行的方法 + * @param args 参数列表 + * @return 方法执行结果 + */ + abstract fun exec(proxy: Any, method: Method, args: Array): Any? +} \ No newline at end of file diff --git a/src/gaea.spring/src/main/kotlin/com/synebula/gaea/spring/autoconfig/ProxyType.kt b/src/gaea.spring/src/main/kotlin/com/synebula/gaea/spring/autoconfig/ProxyType.kt new file mode 100644 index 0000000..7ba44cc --- /dev/null +++ b/src/gaea.spring/src/main/kotlin/com/synebula/gaea/spring/autoconfig/ProxyType.kt @@ -0,0 +1,3 @@ +package com.synebula.gaea.spring.autoconfig + +enum class ProxyType { JDK, Cglib } \ No newline at end of file diff --git a/src/gaea.spring/src/main/kotlin/com/synebula/gaea/spring/autoconfig/Register.kt b/src/gaea.spring/src/main/kotlin/com/synebula/gaea/spring/autoconfig/Register.kt new file mode 100644 index 0000000..f9d70d5 --- /dev/null +++ b/src/gaea.spring/src/main/kotlin/com/synebula/gaea/spring/autoconfig/Register.kt @@ -0,0 +1,109 @@ +package com.synebula.gaea.spring.autoconfig + +import org.springframework.beans.BeansException +import org.springframework.beans.factory.BeanClassLoaderAware +import org.springframework.beans.factory.BeanFactory +import org.springframework.beans.factory.BeanFactoryAware +import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition +import org.springframework.beans.factory.config.BeanDefinition +import org.springframework.beans.factory.support.BeanDefinitionRegistry +import org.springframework.context.EnvironmentAware +import org.springframework.context.ResourceLoaderAware +import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider +import org.springframework.context.annotation.ImportBeanDefinitionRegistrar +import org.springframework.core.env.Environment +import org.springframework.core.io.ResourceLoader +import org.springframework.core.type.AnnotationMetadata +import org.springframework.core.type.classreading.MetadataReader +import org.springframework.core.type.classreading.MetadataReaderFactory +import org.springframework.core.type.filter.TypeFilter +import org.springframework.util.ClassUtils +import java.util.* + +abstract class Register : ImportBeanDefinitionRegistrar, ResourceLoaderAware, BeanClassLoaderAware, + EnvironmentAware, BeanFactoryAware { + + protected var _classLoader: ClassLoader? = null + protected var _environment: Environment? = null + protected var _resourceLoader: ResourceLoader? = null + protected var _beanFactory: BeanFactory? = null + + override fun registerBeanDefinitions(metadata: AnnotationMetadata, registry: BeanDefinitionRegistry) { + val beanDefinitions = this.scan(metadata) + beanDefinitions.forEach { registry.registerBeanDefinition(it.key, it.value) } + } + + abstract fun scan(metadata: AnnotationMetadata): Map + + /** + * 根据过滤器扫描直接包下bean + * + * @param packages 指定的扫描包 + * @param filters 过滤器 + * @return 扫描后的bean定义 + */ + protected fun doScan(packages: Array?, filters: Array): List { + val scanner: ClassPathScanningCandidateComponentProvider = + object : ClassPathScanningCandidateComponentProvider() { + override fun isCandidateComponent(beanDefinition: AnnotatedBeanDefinition): Boolean { + try { + val metadata = beanDefinition.metadata + val target = ClassUtils.forName(metadata.className, _classLoader) + return !target.isAnnotation + } catch (ignored: Exception) { + } + return false + } + } + scanner.environment = _environment!! + scanner.resourceLoader = _resourceLoader!! + for (filter in filters) { + scanner.addIncludeFilter(filter) + } + val beanDefinitions: MutableList = LinkedList() + for (basePackage in packages!!) { + beanDefinitions.addAll(scanner.findCandidateComponents(basePackage)) + } + return beanDefinitions + } + + /** + * 获取指定接口的类型过滤器 + * + * @param interfaces 需要过滤的父接口类型 + * @param onlyInterface 是否只获取接口类型 + * @return 类型过滤器 + */ + protected fun interfaceFilter(interfaces: Array>, onlyInterface: Boolean = false): TypeFilter { + return TypeFilter { metadataReader: MetadataReader, _: MetadataReaderFactory? -> + // 如果只获取接口类型且当前类型非接口 直接返回 + if (onlyInterface && !metadataReader.annotationMetadata.isInterface) + return@TypeFilter false + + var matched = false + val interfaceNames = metadataReader.classMetadata.interfaceNames + // 如果当前类型继承接口有任一需要过滤的接口则说明复合条件 + for (interfaceName in interfaceNames) { + matched = interfaces.any { clazz -> clazz.name == interfaceName } + } + matched + } + } + + override fun setResourceLoader(resourceLoader: ResourceLoader) { + this._resourceLoader = resourceLoader + } + + override fun setBeanClassLoader(classLoader: ClassLoader) { + this._classLoader = classLoader + } + + override fun setEnvironment(environment: Environment) { + this._environment = environment + } + + @Throws(BeansException::class) + override fun setBeanFactory(beanFactory: BeanFactory) { + this._beanFactory = beanFactory + } +} \ No newline at end of file diff --git a/src/gaea/src/main/kotlin/com/synebula/gaea/domain/repository/IRepository.kt b/src/gaea/src/main/kotlin/com/synebula/gaea/domain/repository/IRepository.kt index 67d4ea2..99c411a 100644 --- a/src/gaea/src/main/kotlin/com/synebula/gaea/domain/repository/IRepository.kt +++ b/src/gaea/src/main/kotlin/com/synebula/gaea/domain/repository/IRepository.kt @@ -6,22 +6,29 @@ import com.synebula.gaea.domain.model.IAggregateRoot * 定义了提供增删改的仓储接口。 * 本接口泛型放置到方法上,并需要显式提供聚合根的class对象 */ -interface IRepository { +interface IRepository, ID> { + + /** + * 仓储的对象类 + */ + var clazz: Class + /** * 插入单个对象。 * * @param obj 需要插入的对象。 * @return 返回原对象,如果对象ID为自增,则补充自增ID。 */ - fun , ID> add(obj: TAggregateRoot, clazz: Class) + fun add(obj: TAggregateRoot) /** * 插入多个个对象。 * - * @param obj 需要插入的对象。 + * @param list 需要插入的对象。 * @return 返回原对象,如果对象ID为自增,则补充自增ID。 */ - fun , ID> add(obj: List, clazz: Class) + fun add(list: List) + /** * 更新对象。 @@ -29,24 +36,30 @@ interface IRepository { * @param obj 需要更新的对象。 * @return */ - fun , ID> update(obj: TAggregateRoot, clazz: Class) + fun update(obj: TAggregateRoot) + + /** + * 更新多个个对象。 + * + * @param list 需要新的对象。 + */ + fun update(list: List) /** * 通过id删除该条数据 * - * @param id id - * @param clazz 操作数据的类型 + * @param id 对象ID。 + * @return */ - fun , ID> remove(id: ID, clazz: Class) + fun remove(id: ID) /** * 根据ID获取对象。 * - * @param id id - * @param clazz 操作数据的类型 - * @return 聚合根 + * @param id 对象ID。 + * @return */ - fun , ID> get(id: ID, clazz: Class): TAggregateRoot? + fun get(id: ID): TAggregateRoot? /** @@ -55,5 +68,7 @@ interface IRepository { * @param params 查询条件。 * @return int */ - fun count(params: Map?, clazz: Class): Int + fun count(params: Map?): Int + } + diff --git a/src/gaea/src/main/kotlin/com/synebula/gaea/domain/repository/ISpecificRepository.kt b/src/gaea/src/main/kotlin/com/synebula/gaea/domain/repository/ISpecificRepository.kt deleted file mode 100644 index e9501c0..0000000 --- a/src/gaea/src/main/kotlin/com/synebula/gaea/domain/repository/ISpecificRepository.kt +++ /dev/null @@ -1,61 +0,0 @@ -package com.synebula.gaea.domain.repository - -import com.synebula.gaea.domain.model.IAggregateRoot - -/** - * 继承本接口表示对象为仓储类。 - * 定义了提供增删改的仓储接口。 - * 本接口泛型定义在类上,方法中不需要显式提供聚合根的class对象,class对象作为类的成员变量声明。 - * - * @param TAggregateRoot 聚合根类型 - * @author alex - */ -interface ISpecificRepository, ID> { - - /** - * 仓储的对象类 - */ - var clazz: Class? - - /** - * 插入单个对象。 - * - * @param obj 需要插入的对象。 - * @return 返回原对象,如果对象ID为自增,则补充自增ID。 - */ - fun add(obj: TAggregateRoot) - - /** - * 更新对象。 - * - * @param obj 需要更新的对象。 - * @return - */ - fun update(obj: TAggregateRoot) - - /** - * 通过id删除该条数据 - * - * @param id 对象ID。 - * @return - */ - fun remove(id: ID) - - /** - * 根据ID获取对象。 - * - * @param id 对象ID。 - * @return - */ - fun get(id: ID): TAggregateRoot - - - /** - * 根据条件查询符合条件记录的数量 - * - * @param params 查询条件。 - * @return int - */ - fun count(params: Map?): Int - -} diff --git a/src/gaea/src/main/kotlin/com/synebula/gaea/domain/repository/IUniversalRepository.kt b/src/gaea/src/main/kotlin/com/synebula/gaea/domain/repository/IUniversalRepository.kt new file mode 100644 index 0000000..8eaca7e --- /dev/null +++ b/src/gaea/src/main/kotlin/com/synebula/gaea/domain/repository/IUniversalRepository.kt @@ -0,0 +1,65 @@ +package com.synebula.gaea.domain.repository + +import com.synebula.gaea.domain.model.IAggregateRoot + +/** + * 定义了提供增删改的仓储接口。 + * 本接口泛型放置到方法上,并需要显式提供聚合根的class对象 + */ +interface IUniversalRepository { + /** + * 插入单个对象。 + * + * @param root 需要插入的对象。 + * @return 返回原对象,如果对象ID为自增,则补充自增ID。 + */ + fun , ID> add(root: TAggregateRoot, clazz: Class) + + /** + * 插入多个个对象。 + * + * @param roots 需要插入的对象。 + */ + fun , ID> add(roots: List, clazz: Class) + + /** + * 更新对象。 + * + * @param root 需要更新的对象。 + * @return + */ + fun , ID> update(root: TAggregateRoot, clazz: Class) + + /** + * 更新多个个对象。 + * + * @param roots 需要更新的对象。 + */ + fun , ID> update(roots: List, clazz: Class) + + /** + * 通过id删除该条数据 + * + * @param id id + * @param clazz 操作数据的类型 + */ + fun , ID> remove(id: ID, clazz: Class) + + /** + * 根据ID获取对象。 + * + * @param id id + * @param clazz 操作数据的类型 + * @return 聚合根 + */ + fun , ID> get(id: ID, clazz: Class): TAggregateRoot? + + + /** + * 根据条件查询符合条件记录的数量 + * + * @param params 查询条件。 + * @return int + */ + fun count(params: Map?, clazz: Class): Int +} diff --git a/src/gaea/src/main/kotlin/com/synebula/gaea/domain/service/IService.kt b/src/gaea/src/main/kotlin/com/synebula/gaea/domain/service/IService.kt index 6cabe08..82f26d6 100644 --- a/src/gaea/src/main/kotlin/com/synebula/gaea/domain/service/IService.kt +++ b/src/gaea/src/main/kotlin/com/synebula/gaea/domain/service/IService.kt @@ -1,8 +1,6 @@ package com.synebula.gaea.domain.service import com.synebula.gaea.data.message.DataMessage -import com.synebula.gaea.data.message.StatusMessage -import com.synebula.gaea.log.ILogger /** @@ -12,27 +10,39 @@ import com.synebula.gaea.log.ILogger * @since 2016年9月18日 下午2:23:15 */ interface IService { - /** - * 日志组件。 - */ - var logger: ILogger + /** + * 增加对象 + * + * @param command 增加对象命令 + */ fun add(command: ICommand): DataMessage + /** + * 增加对象 + * + * @param commands 增加对象命令列表 + */ + fun add(commands: List) + + /** + * 更新对象 + * + * @param id 对象ID + * @param command 更新对象命令 + */ fun update(id: ID, command: ICommand) + /** + * 批量更新对象 + * + * @param commands 更新对象命令列表 + */ + fun update(commands: List) + + /** + * 增加对象 + * @param id 对象ID + */ fun remove(id: ID) - - /** - * 添加一个删除对象前执行监听器。 - * @param key 监听器标志。 - * @param func 监听方法。 - */ - fun addBeforeRemoveListener(key: String, func: (id: ID) -> StatusMessage) - - /** - * 移除一个删除对象前执行监听器。 - * @param key 监听器标志。 - */ - fun removeBeforeRemoveListener(key: String) } diff --git a/src/gaea/src/main/kotlin/com/synebula/gaea/domain/service/ISimpleService.kt b/src/gaea/src/main/kotlin/com/synebula/gaea/domain/service/ISimpleService.kt index 6d8fbff..ad7b5bc 100644 --- a/src/gaea/src/main/kotlin/com/synebula/gaea/domain/service/ISimpleService.kt +++ b/src/gaea/src/main/kotlin/com/synebula/gaea/domain/service/ISimpleService.kt @@ -1,7 +1,6 @@ package com.synebula.gaea.domain.service import com.synebula.gaea.data.message.DataMessage -import com.synebula.gaea.data.message.StatusMessage import com.synebula.gaea.domain.model.IAggregateRoot import com.synebula.gaea.log.ILogger @@ -18,22 +17,38 @@ interface ISimpleService, ID> { */ var logger: ILogger + /** + * 增加对象 + * + * @param root 增加对象命令 + */ fun add(root: TAggregateRoot): DataMessage + /** + * 增加对象 + * + * @param roots 增加对象命令列表 + */ + fun add(roots: List) + + /** + * 更新对象 + * + * @param id 对象ID + * @param root 更新对象命令 + */ fun update(id: ID, root: TAggregateRoot) + /** + * 批量更新对象 + * + * @param roots 更新对象命令列表 + */ + fun update(roots: List) + + /** + * 增加对象 + * @param id 对象ID + */ fun remove(id: ID) - - /** - * 添加一个删除对象前执行监听器。 - * @param key 监听器标志。 - * @param func 监听方法。 - */ - fun addBeforeRemoveListener(key: String, func: (id: ID) -> StatusMessage) - - /** - * 移除一个删除对象前执行监听器。 - * @param key 监听器标志。 - */ - fun removeBeforeRemoveListener(key: String) } diff --git a/src/gaea/src/main/kotlin/com/synebula/gaea/domain/service/Service.kt b/src/gaea/src/main/kotlin/com/synebula/gaea/domain/service/Service.kt index eee85ec..264a258 100644 --- a/src/gaea/src/main/kotlin/com/synebula/gaea/domain/service/Service.kt +++ b/src/gaea/src/main/kotlin/com/synebula/gaea/domain/service/Service.kt @@ -1,78 +1,80 @@ package com.synebula.gaea.domain.service import com.synebula.gaea.data.message.DataMessage -import com.synebula.gaea.data.message.StatusMessage import com.synebula.gaea.data.serialization.IObjectMapper import com.synebula.gaea.domain.model.IAggregateRoot import com.synebula.gaea.domain.repository.IRepository -import com.synebula.gaea.log.ILogger /** - * 依赖了IRepository仓储借口的服务实现类 Service - * 该类依赖仓储接口 @see IRepository, 需要显式提供聚合根的class对象 + * 依赖了IRepository仓储借口的服务实现类 GenericsService + * 该类依赖仓储接口 @see IGenericsRepository, 需要显式提供聚合根的class对象 * - * @param repository 仓储对象 * @param clazz 聚合根类对象 - * @param deserializer 对象转换组件 - * @param logger 日志组件 + * @param repo 仓储对象 + * @param mapper 对象转换组件 * @author alex * @version 0.1 * @since 2020-05-17 */ -open class Service, ID>( - protected open var clazz: Class, - protected open var repository: IRepository, - protected open var deserializer: IObjectMapper, - override var logger: ILogger, +open class Service, ID>( + protected open var clazz: Class, + protected open var repo: IRepository, + protected open var mapper: IObjectMapper, ) : IService { - /** - * 删除对象前执行监听器。 - */ - protected val beforeRemoveListeners = mutableMapOf StatusMessage>() /** - * 添加一个删除对象前执行监听器。 - * @param key 监听器标志。 - * @param func 监听方法。 + * 增加对象 + * + * @param command 增加对象命令 */ - override fun addBeforeRemoveListener(key: String, func: (id: ID) -> StatusMessage) { - this.beforeRemoveListeners[key] = func - } - - /** - * 移除一个删除对象前执行监听器。 - * @param key 监听器标志。 - */ - override fun removeBeforeRemoveListener(key: String) { - this.beforeRemoveListeners.remove(key) - } - override fun add(command: ICommand): DataMessage { val msg = DataMessage() - val root = this.deserialize(command) - this.repository.add(root, this.clazz) + val root = this.map(command) + this.repo.add(root) msg.data = root.id return msg } - override fun update(id: ID, command: ICommand) { - val root = this.deserialize(command) - root.id = id - this.repository.update(root, this.clazz) + /** + * 增加对象 + * + * @param commands 增加对象命令列表 + */ + override fun add(commands: List) { + val roots = commands.map { this.map(it) } + this.repo.add(roots) } + /** + * 更新对象 + * + * @param id 对象ID + * @param command 更新对象命令 + */ + override fun update(id: ID, command: ICommand) { + val root = this.map(command) + root.id = id + this.repo.update(root) + } + + /** + * 批量更新对象 + * + * @param commands 更新对象命令列表 + */ + override fun update(commands: List) { + val roots = commands.map { this.map(it) } + this.repo.update(roots) + } + + /** + * 增加对象 + * @param id 对象ID + */ override fun remove(id: ID) { - val functions = this.beforeRemoveListeners.values - var msg: StatusMessage - for (func in functions) { - msg = func(id) - if (!msg.success()) { - throw IllegalStateException(msg.message) - } - } - this.repository.remove(id, this.clazz) + this.repo.remove(id) } /** @@ -81,9 +83,9 @@ open class Service, ID>( * @param command 需要转换的命令 * @return 聚合根 */ - protected open fun deserialize(command: ICommand): TAggregateRoot { + protected open fun map(command: ICommand): TRoot { try { - return deserializer.deserialize(command, this.clazz) + return mapper.deserialize(command, this.clazz) } catch (ex: Exception) { throw RuntimeException("command not match aggregate root", ex) } diff --git a/src/gaea/src/main/kotlin/com/synebula/gaea/domain/service/ServiceDependency.kt b/src/gaea/src/main/kotlin/com/synebula/gaea/domain/service/ServiceDependency.kt new file mode 100644 index 0000000..42e0c2b --- /dev/null +++ b/src/gaea/src/main/kotlin/com/synebula/gaea/domain/service/ServiceDependency.kt @@ -0,0 +1,16 @@ +package com.synebula.gaea.domain.service + +import com.synebula.gaea.domain.model.IAggregateRoot +import com.synebula.gaea.domain.repository.IRepository +import kotlin.reflect.KClass + +/** + * 声明服务的依赖项,若服务没有实现类则可以根据依赖项自动组装服务。 + * + * @param clazz 依赖的聚合根类型 + * @param repo 依赖的[IRepository]类型 + */ +annotation class ServiceDependency( + val clazz: KClass>, + val repo: KClass>, +) diff --git a/src/gaea/src/main/kotlin/com/synebula/gaea/domain/service/SimpleService.kt b/src/gaea/src/main/kotlin/com/synebula/gaea/domain/service/SimpleService.kt index 1a216bc..3c31c8e 100644 --- a/src/gaea/src/main/kotlin/com/synebula/gaea/domain/service/SimpleService.kt +++ b/src/gaea/src/main/kotlin/com/synebula/gaea/domain/service/SimpleService.kt @@ -1,15 +1,14 @@ package com.synebula.gaea.domain.service import com.synebula.gaea.data.message.DataMessage -import com.synebula.gaea.data.message.StatusMessage import com.synebula.gaea.domain.model.IAggregateRoot import com.synebula.gaea.domain.repository.IRepository import com.synebula.gaea.log.ILogger /** - * 依赖了IRepository仓储借口的服务实现类 Service - * 该类依赖仓储接口 @see IRepository, 需要显式提供聚合根的class对象 + * 依赖了IRepository仓储借口的服务实现类 GenericsService + * 该类依赖仓储接口 @see IGenericsRepository, 需要显式提供聚合根的class对象 * * @param repository 仓储对象 * @param clazz 聚合根类对象 @@ -20,53 +19,41 @@ import com.synebula.gaea.log.ILogger */ open class SimpleService, ID>( protected open var clazz: Class, - protected open var repository: IRepository, + protected open var repository: IRepository, override var logger: ILogger, ) : ISimpleService { - /** - * 删除对象前执行监听器。 - */ - protected val beforeRemoveListeners = mutableMapOf StatusMessage>() - - /** - * 添加一个删除对象前执行监听器。 - * @param key 监听器标志。 - * @param func 监听方法。 - */ - override fun addBeforeRemoveListener(key: String, func: (id: ID) -> StatusMessage) { - this.beforeRemoveListeners[key] = func - } - - /** - * 移除一个删除对象前执行监听器。 - * @param key 监听器标志。 - */ - override fun removeBeforeRemoveListener(key: String) { - this.beforeRemoveListeners.remove(key) - } - override fun add(root: TAggregateRoot): DataMessage { val msg = DataMessage() - this.repository.add(root, this.clazz) + this.repository.add(root) msg.data = root.id return msg } override fun update(id: ID, root: TAggregateRoot) { root.id = id - this.repository.update(root, this.clazz) + this.repository.update(root) } override fun remove(id: ID) { - val functions = this.beforeRemoveListeners.values - var msg: StatusMessage - for (func in functions) { - msg = func(id) - if (!msg.success()) { - throw IllegalStateException(msg.message) - } - } - this.repository.remove(id, this.clazz) + this.repository.remove(id) + } + + /** + * 增加对象 + * + * @param roots 增加对象命令列表 + */ + override fun add(roots: List) { + this.repository.add(roots) + } + + /** + * 批量更新对象 + * + * @param roots 更新对象命令列表 + */ + override fun update(roots: List) { + this.repository.update(roots) } } diff --git a/src/gaea/src/main/kotlin/com/synebula/gaea/query/IQuery.kt b/src/gaea/src/main/kotlin/com/synebula/gaea/query/IQuery.kt index adce2a8..1f2aa50 100644 --- a/src/gaea/src/main/kotlin/com/synebula/gaea/query/IQuery.kt +++ b/src/gaea/src/main/kotlin/com/synebula/gaea/query/IQuery.kt @@ -5,22 +5,27 @@ package com.synebula.gaea.query * * @author alex */ -interface IQuery { +interface IQuery { + /** + * 仓储的视图类 + */ + var clazz: Class + /** * 根据Key获取对象。 * * @param id 对象Key。 * @return 视图结果 */ - fun get(id: ID, clazz: Class): TView? + fun get(id: ID): TView? /** * 根据实体类条件查询所有符合条件记录 - * + *` * @param params 查询条件。 * @return 视图列表 */ - fun list(params: Map?, clazz: Class): List + fun list(params: Map?): List /** * 根据条件查询符合条件记录的数量 @@ -28,7 +33,7 @@ interface IQuery { * @param params 查询条件。 * @return 数量 */ - fun count(params: Map?, clazz: Class): Int + fun count(params: Map?): Int /** * 根据实体类条件查询所有符合条件记录(分页查询) @@ -36,7 +41,7 @@ interface IQuery { * @param params 分页条件 * @return 分页数据 */ - fun paging(params: Params, clazz: Class): Page + fun paging(params: Params): Page /** * 查询条件范围内数据。 @@ -45,5 +50,5 @@ interface IQuery { * * @return 视图列表 */ - fun range(field: String, params: List, clazz: Class): List + fun range(field: String, params: List): List } diff --git a/src/gaea/src/main/kotlin/com/synebula/gaea/query/ISpecificQuery.kt b/src/gaea/src/main/kotlin/com/synebula/gaea/query/IUniversalQuery.kt similarity index 61% rename from src/gaea/src/main/kotlin/com/synebula/gaea/query/ISpecificQuery.kt rename to src/gaea/src/main/kotlin/com/synebula/gaea/query/IUniversalQuery.kt index fbe4c77..05929ab 100644 --- a/src/gaea/src/main/kotlin/com/synebula/gaea/query/ISpecificQuery.kt +++ b/src/gaea/src/main/kotlin/com/synebula/gaea/query/IUniversalQuery.kt @@ -1,18 +1,18 @@ package com.synebula.gaea.query /** - * 查询基接口。 - * 本接口泛型定义在类上,方法中不需要显式提供聚合根的class对象,class对象作为类的成员变量声明。 + * 查询基接口, 其中方法都指定了查询的视图类型。 + * * @author alex */ -interface ISpecificQuery { +interface IUniversalQuery { /** * 根据Key获取对象。 * * @param id 对象Key。 * @return 视图结果 */ - fun get(id: ID): TView? + fun get(id: ID, clazz: Class): TView? /** * 根据实体类条件查询所有符合条件记录 @@ -20,7 +20,7 @@ interface ISpecificQuery { * @param params 查询条件。 * @return 视图列表 */ - fun list(params: Map?): List + fun list(params: Map?, clazz: Class): List /** * 根据条件查询符合条件记录的数量 @@ -28,7 +28,7 @@ interface ISpecificQuery { * @param params 查询条件。 * @return 数量 */ - fun count(params: Map?): Int + fun count(params: Map?, clazz: Class): Int /** * 根据实体类条件查询所有符合条件记录(分页查询) @@ -36,7 +36,7 @@ interface ISpecificQuery { * @param params 分页条件 * @return 分页数据 */ - fun paging(params: Params): Page + fun paging(params: Params, clazz: Class): Page /** * 查询条件范围内数据。 @@ -45,5 +45,5 @@ interface ISpecificQuery { * * @return 视图列表 */ - fun range(field: String, params: List): List + fun range(field: String, params: List, clazz: Class): List } diff --git a/src/gaea/src/main/kotlin/com/synebula/gaea/query/type/Operator.kt b/src/gaea/src/main/kotlin/com/synebula/gaea/query/Operator.kt similarity index 92% rename from src/gaea/src/main/kotlin/com/synebula/gaea/query/type/Operator.kt rename to src/gaea/src/main/kotlin/com/synebula/gaea/query/Operator.kt index e3ece94..523cf30 100644 --- a/src/gaea/src/main/kotlin/com/synebula/gaea/query/type/Operator.kt +++ b/src/gaea/src/main/kotlin/com/synebula/gaea/query/Operator.kt @@ -1,4 +1,4 @@ -package com.synebula.gaea.query.type +package com.synebula.gaea.query enum class Operator { /** diff --git a/src/gaea/src/main/kotlin/com/synebula/gaea/query/type/Order.kt b/src/gaea/src/main/kotlin/com/synebula/gaea/query/Order.kt similarity index 84% rename from src/gaea/src/main/kotlin/com/synebula/gaea/query/type/Order.kt rename to src/gaea/src/main/kotlin/com/synebula/gaea/query/Order.kt index 35cd05f..8fdeba1 100644 --- a/src/gaea/src/main/kotlin/com/synebula/gaea/query/type/Order.kt +++ b/src/gaea/src/main/kotlin/com/synebula/gaea/query/Order.kt @@ -1,4 +1,4 @@ -package com.synebula.gaea.query.type +package com.synebula.gaea.query /** * class OrderType diff --git a/src/gaea/src/main/kotlin/com/synebula/gaea/query/Params.kt b/src/gaea/src/main/kotlin/com/synebula/gaea/query/Params.kt index 0362126..ed6ed3b 100644 --- a/src/gaea/src/main/kotlin/com/synebula/gaea/query/Params.kt +++ b/src/gaea/src/main/kotlin/com/synebula/gaea/query/Params.kt @@ -1,7 +1,5 @@ package com.synebula.gaea.query -import com.synebula.gaea.query.type.Order - /** * class 分页参数信息 * diff --git a/src/gaea/src/main/kotlin/com/synebula/gaea/query/annotation/Table.kt b/src/gaea/src/main/kotlin/com/synebula/gaea/query/Table.kt similarity index 51% rename from src/gaea/src/main/kotlin/com/synebula/gaea/query/annotation/Table.kt rename to src/gaea/src/main/kotlin/com/synebula/gaea/query/Table.kt index 00d7922..59431c1 100644 --- a/src/gaea/src/main/kotlin/com/synebula/gaea/query/annotation/Table.kt +++ b/src/gaea/src/main/kotlin/com/synebula/gaea/query/Table.kt @@ -1,3 +1,3 @@ -package com.synebula.gaea.query.annotation +package com.synebula.gaea.query annotation class Table(val name: String = "") \ No newline at end of file diff --git a/src/gaea/src/main/kotlin/com/synebula/gaea/query/annotation/Where.kt b/src/gaea/src/main/kotlin/com/synebula/gaea/query/Where.kt similarity index 83% rename from src/gaea/src/main/kotlin/com/synebula/gaea/query/annotation/Where.kt rename to src/gaea/src/main/kotlin/com/synebula/gaea/query/Where.kt index 8170cf3..1e06df3 100644 --- a/src/gaea/src/main/kotlin/com/synebula/gaea/query/annotation/Where.kt +++ b/src/gaea/src/main/kotlin/com/synebula/gaea/query/Where.kt @@ -1,6 +1,4 @@ -package com.synebula.gaea.query.annotation - -import com.synebula.gaea.query.type.Operator +package com.synebula.gaea.query /** * 字段注解,规定字段的查询方式 diff --git a/src/gaea/src/main/kotlin/com/synebula/gaea/reflect/Types.kt b/src/gaea/src/main/kotlin/com/synebula/gaea/reflect/Types.kt index 75ac061..28a137e 100644 --- a/src/gaea/src/main/kotlin/com/synebula/gaea/reflect/Types.kt +++ b/src/gaea/src/main/kotlin/com/synebula/gaea/reflect/Types.kt @@ -1,7 +1,5 @@ package com.synebula.gaea.reflect -import com.synebula.gaea.bus.SubscriberRegistry - object Types { /** * 获取类的所有父类型。 @@ -9,15 +7,15 @@ object Types { fun supertypes(clazz: Class<*>): Set> { val supertypes = mutableSetOf>() supertypes.add(clazz) - if (clazz.superclass != null) - supertypes.addAll(SubscriberRegistry.flattenHierarchy(clazz.superclass)) if (clazz.interfaces.isNotEmpty()) { - supertypes.addAll(clazz.interfaces.map { SubscriberRegistry.flattenHierarchy(it) }.reduce { r, c -> + supertypes.addAll(clazz.interfaces.map { supertypes(it) }.reduce { r, c -> val all = r.toMutableSet() all.addAll(c) all }) } + if (clazz.superclass != null) + supertypes.addAll(supertypes(clazz.superclass)) return supertypes } } \ No newline at end of file