您可以通过一些我称之为“手动 AOP”的方法来实现这一点。
首先定义一些基本特征来捕获将结果包装在 an Option
、 aFuture
或任何其他容器中的概念,以及实际执行包装的 aa 方法:
import concurrent._
trait AbstractService {
type Result[T]
protected def result[T]( code: => T ) : Result[T]
}
然后将这个基本特征专门用于Future
和Option
情况:
trait SyncService extends AbstractService {
type Result[T] = Option[T]
// Returns the original result wrapped in Some,
// or None if it was null or an exception occured
protected def result[T]( code: => T ) : Option[T] = {
try {
Option( code )
} catch{ case ex: Throwable =>
ex.printStackTrace()
None
}
}
}
trait AsyncService extends AbstractService {
type Result[T] = Future[T]
protected val execContext: ExecutionContext
protected def result[T]( code: => T ) : Future[T] = {
future( code )( execContext )
}
}
现在您可以开始了,可以像这样定义您的 EntityGetService 特征:
trait EntityGetService[ID, ENTITY] extends AbstractService {
def get( id: ID ): Result[ENTITY] = result {
???
}
// add all the other method implementations here, taking care to
// wrap the method bodies inside "result"
}
// Now specializing EntityGetService as a sync or async service is just a matter
// of mixing SyncService or AsyncService:
class EntitySyncGetService[Long, Entity] extends EntityGetService[Long, Entity] with SyncService
class EntityAsyncGetService[Long, Entity]( implicit val execContext: ExecutionContext ) extends EntityGetService[Long, Entity] with AsyncService