如何让Storage trait实现类的NonFatal异常自动包装为StorageWriteException?
统一处理Storage实现类的异常包装方案
完全不需要在每个实现类里手动包装异常!我们可以利用Scala trait的特性,把异常捕获逻辑统一封装在trait层面,让子类只需要专注于实现实际的写入逻辑就行。
具体实现步骤
- 改造Storage trait
把原来的抽象write方法改成具体方法,同时新增一个受保护的抽象方法(比如doWrite)让子类实现实际写入逻辑。在trait的write方法里统一处理异常捕获和包装:
import scala.util.control.NonFatal trait Storage { // 对外暴露的公共方法,由trait统一实现异常包装 def write(data: Array[Byte]): Unit = { try { doWrite(data) } catch { case NonFatal(e) => throw new StorageWriteException(e) } } // 子类必须实现的实际写入逻辑,protected限制只能子类访问 protected def doWrite(data: Array[Byte]): Unit }
- 保留你的异常类
class StorageWriteException(t: Throwable) extends RuntimeException(t)
- 子类实现示例
子类只需要专注于实现doWrite方法,完全不用管异常处理——所有NonFatal异常都会被父trait的write方法自动捕获并包装:
import java.io.FileOutputStream class FileStorage(path: String) extends Storage { override protected def doWrite(data: Array[Byte]): Unit = { val fos = new FileOutputStream(path) try { fos.write(data) } finally { fos.close() } // 这里如果抛出IO异常等NonFatal异常,会被自动包装成StorageWriteException } }
关键说明
- 避免子类重写write方法:如果子类重写了
write,会覆盖trait里的异常处理逻辑,所以要提醒实现者只需要实现doWrite即可。如果确实需要扩展write,记得调用super.write(data)来复用统一的异常包装逻辑。 - NonFatal的范围:Scala的
NonFatal排除了VM错误、线程死亡等致命异常,这些异常通常不需要我们包装,交给JVM处理更合适,所以这个范围刚好符合业务需求。
内容的提问来源于stack exchange,提问作者Some Name
相关产品推荐
相关产品推荐

