1.2.0 增加 IRepository IQuery的工厂方法,避免无用的空白接口编写

This commit is contained in:
2022-08-22 15:16:41 +08:00
parent 3c23c26a64
commit 53709b6fc3
9 changed files with 127 additions and 24 deletions

View File

@@ -17,7 +17,7 @@ buildscript {
subprojects {
group 'com.synebula'
version '1.1.2'
version '1.2.0'
buildscript {
repositories {

View File

@@ -2,16 +2,18 @@ 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.repository.IRepositoryFactory
import com.synebula.gaea.domain.service.Domain
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<String> = arrayOf()
private var supertype: Class<*>,
private var beanFactory: BeanFactory, implementBeanNames: Array<String> = arrayOf()
) : Proxy() {
private var service: IService<*>
@@ -20,18 +22,26 @@ class ServiceProxy(
// 如果没有实现类, 使用Service类代理
if (implementBeanNames.isEmpty()) {
// 如果没有实现类并且没有ServiceDependency注解, 则抛出异常
if (!this.supertype.declaredAnnotations.any { it.annotationClass == ServiceDependency::class }) {
if (!this.supertype.declaredAnnotations.any { it.annotationClass == Domain::class }) {
throw InvalidClassException(
"interface ${this.supertype.name} must has implementation class or annotation by ${ServiceDependency::class.qualifiedName}"
"interface ${this.supertype.name} must has implementation class or annotation by ${Domain::class.qualifiedName}"
)
}
val serviceDependency = this.supertype.getDeclaredAnnotation(ServiceDependency::class.java)
val repo = this.beanFactory.getBean(serviceDependency.repo.java)
val domain = this.supertype.getDeclaredAnnotation(Domain::class.java)
// repository工厂对象
val defaultRepositoryFactory = this.beanFactory.getBean(IRepositoryFactory::class.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)
this.service =
constructor.newInstance(
domain.clazz.java,
defaultRepositoryFactory.createRawRepository(domain.clazz.java),
mapper
)
} else {
this.service = this.beanFactory.getBean(implementBeanNames[0]) as IService<*>
}

View File

@@ -51,4 +51,16 @@ class MongodbRepoRegister : Register() {
}
return result
}
private fun addDefaultProxyBean(result: MutableMap<String, BeanDefinition>) {
// IRepository proxy
val builder = BeanDefinitionBuilder.genericBeanDefinition(IRepository::class.java)
builder.addConstructorArgValue(IRepository::class.java)
builder.addConstructorArgValue(this._beanFactory)
builder.addConstructorArgValue(emptyArray<String>())
val definition = builder.rawBeanDefinition as GenericBeanDefinition
definition.beanClass = MongodbRepoFactory::class.java
definition.autowireMode = GenericBeanDefinition.AUTOWIRE_BY_TYPE
result[IRepository::class.java.name] = definition
}
}

View File

@@ -0,0 +1,23 @@
package com.synebula.gaea.mongodb.query
import com.synebula.gaea.query.IQuery
import com.synebula.gaea.query.IQueryFactory
import org.springframework.data.mongodb.core.MongoTemplate
class MongodbQueryFactory(var template: MongoTemplate) : IQueryFactory {
/**
* 创建IQuery接口类型
*/
override fun createRawQuery(clazz: Class<*>): IQuery<*, *> {
val constructor = MongodbQuery::class.java.getConstructor(Class::class.java, MongoTemplate::class.java)
return constructor.newInstance(clazz, this.template)
}
/**
* 创建IQuery接口类型
*/
override fun <T, I> createQuery(clazz: Class<T>): IQuery<T, I> {
return MongodbQuery(clazz, template)
}
}

View File

@@ -0,0 +1,24 @@
package com.synebula.gaea.mongodb.repository
import com.synebula.gaea.domain.model.IAggregateRoot
import com.synebula.gaea.domain.repository.IRepository
import com.synebula.gaea.domain.repository.IRepositoryFactory
import org.springframework.data.mongodb.core.MongoTemplate
class MongodbRepositoryFactory(var template: MongoTemplate) : IRepositoryFactory {
/**
* 创建IRepository接口类型
*/
override fun createRawRepository(clazz: Class<*>): IRepository<*, *> {
val constructor = MongodbRepository::class.java.getConstructor(Class::class.java, MongoTemplate::class.java)
return constructor.newInstance(clazz, this.template)
}
/**
* 创建IRepository接口类型
*/
override fun <T : IAggregateRoot<I>, I> createRepository(clazz: Class<T>): IRepository<T, I> {
return MongodbRepository(clazz, template)
}
}

View File

@@ -0,0 +1,19 @@
package com.synebula.gaea.domain.repository
import com.synebula.gaea.domain.model.IAggregateRoot
/**
* Repository 工厂接口。 定义了Repository的创建方法。
*/
interface IRepositoryFactory {
/**
* 创建原始类型的IRepository接口类型
*/
fun createRawRepository(clazz: Class<*>): IRepository<*, *>
/**
* 创建指定类型的IRepository接口类型
*/
fun <T : IAggregateRoot<I>, I> createRepository(clazz: Class<T>): IRepository<T, I>
}

View File

@@ -0,0 +1,13 @@
package com.synebula.gaea.domain.service
import com.synebula.gaea.domain.model.IAggregateRoot
import kotlin.reflect.KClass
/**
* 声明服务依赖的聚合根,若服务没有实现类则可以根据依赖项自动组装服务。
*
* @param clazz 依赖的聚合根类型
*/
@Target(AnnotationTarget.CLASS)
@Retention(AnnotationRetention.RUNTIME)
annotation class Domain(val clazz: KClass<out IAggregateRoot<*>>)

View File

@@ -1,16 +0,0 @@
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<out IAggregateRoot<*>>,
val repo: KClass<out IRepository<*, *>>,
)

View File

@@ -0,0 +1,18 @@
package com.synebula.gaea.query
/**
* Query 工厂接口。 定义了Query的创建方法。
*/
interface IQueryFactory {
/**
* 创建原始类型的IQuery接口类型
*/
fun createRawQuery(clazz: Class<*>): IQuery<*, *>
/**
* 创建指定类型的IQuery接口类型
*/
fun <T, I> createQuery(clazz: Class<T>): IQuery<T, I>
}