-
airframe-di: Dependency Injectionscala/airframe 2022. 11. 19. 22:42
airframe-di 를 이용한 Dependency Injection
maven repo: https://mvnrepository.com/artifact/org.wvlet.airframe/airframe
아래정도 기능만 사용하는 것이 좋을 것 같다.
https://wvlet.org/airframe/docs/airframe-di#child-sessions 등을 사용하면 테스트나 코드 읽기가 힘들어질 것 같다.
Note:
- +(add) operator 로 design 을 합치거나 override(lazy) 할 수 있다.
- lazy 하게 적용되기 때문에, 필요한 components 를 나중에 +(add) operator 로 제공되어도 괜찮다.
- bind[T].toProvider(...) 이것 덕분에 복잡할 수 있는 코드가 많이 간결해 진다.
import wvlet.airframe._ object ScalaApp { type Env = String case class Config(id: String, ip: String, port: Int) class App(config: Config, urlMaker: UrlMaker, remoteQuery: RemoteServer) { def run(): Unit = { println(s"ID: ${config.id}") val url = urlMaker.getURL val info = remoteQuery.getInfo(url) println(s"INFO: $info") } } private class UrlMaker(config: Config) { def getURL: String = s"http://${config.ip}:${config.port}/${config.id}" } class RemoteServer(val env: Env, id: String) { def getInfo(url: String): String = s"RESPONSE [server=$id]: $url" } def main(args: Array[String]): Unit = { val coreDesign: Design = newDesign .bind[Config].toInstance(Config("id_123", "127.0.0.1", 8080)) // Lazy .bind[UrlMaker].toSingleton // Env 가 core Design 에 없더라도 '+' operator 로 나중에 제공되어도 좋다!! .bind[RemoteServer] .toProvider((config: Config, env: Env) => new RemoteServer(env, config.id)) .onInit { x: RemoteServer => println(s"Start Remote [${x.env}] Server") } .onShutdown { x: RemoteServer => println(s"Stop Remote [${x.env}] Server") } val devMode: Design = newDesign .bind[Env].toInstance("dev") val prodMode: Design = newDesign .bind[Env].toInstance("prod") // val design = coreDesign + devMode val design = coreDesign + prodMode // 혹은 val design = coreDesign.bind[Env].toInstance("prod") design.build[App](app => app.run()) } }
아래처럼 trait 안에서 bind 를 사용해 dependency 를 설정할 수 있다.
import org.apache.spark.sql.{Dataset, SparkSession} import wvlet.airframe.bind trait RecordWriter[A] { val spark: SparkSession = bind[SparkSession] def write(ds: Dataset[A]): Unit } class ConsoleRecordWriter[A] extends RecordWriter[A] { override def write(ds: Dataset[A]): Unit = ds.show() } class HdfsRecordWriter[A](path: String) extends RecordWriter[A] { override def write(ds: Dataset[A]): Unit = ds.write.parquet(path) }
'scala > airframe' 카테고리의 다른 글
airframe-control: Retry (0) 2023.07.06 airframe-control: Parallel (0) 2023.07.06