From 15208dd0254875bef8b6ad1edd6adc77bf419a53 Mon Sep 17 00:00:00 2001 From: Lewuathe Date: Fri, 19 Aug 2016 15:37:03 +0900 Subject: [PATCH] Build EagerSingleton just after Session instantiation --- .../src/main/scala/wvlet/inject/Inject.scala | 4 +++- .../main/scala/wvlet/inject/SessionImpl.scala | 15 +++++++++------ .../test/scala/wvlet/inject/InjectTest.scala | 19 ++++++++++++++++++- 3 files changed, 30 insertions(+), 8 deletions(-) diff --git a/wvlet-inject/src/main/scala/wvlet/inject/Inject.scala b/wvlet-inject/src/main/scala/wvlet/inject/Inject.scala index 8f5ed979..ef9c7bef 100644 --- a/wvlet-inject/src/main/scala/wvlet/inject/Inject.scala +++ b/wvlet-inject/src/main/scala/wvlet/inject/Inject.scala @@ -121,7 +121,9 @@ class Inject extends LogSupport { } val keyIndex : Map[ObjectType, Int] = originalBindings.map(_.from).zipWithIndex.map(x => x._1 -> x._2).toMap val sortedBindings = effectiveBindings.toSeq.sortBy(x => keyIndex(x.from)) - new SessionImpl(sortedBindings, listener.result()) + val s = new SessionImpl(sortedBindings, listener.result()) + s.init() + s } def addBinding(b: Binding): Inject = { diff --git a/wvlet-inject/src/main/scala/wvlet/inject/SessionImpl.scala b/wvlet-inject/src/main/scala/wvlet/inject/SessionImpl.scala index 78075a3c..92996ac8 100644 --- a/wvlet-inject/src/main/scala/wvlet/inject/SessionImpl.scala +++ b/wvlet-inject/src/main/scala/wvlet/inject/SessionImpl.scala @@ -33,12 +33,14 @@ private[inject] class SessionImpl(binding: Seq[Binding], listener: Seq[SessionLi private lazy val singletonHolder: collection.mutable.Map[ObjectType, Any] = new ConcurrentHashMap[ObjectType, Any]() - // Initialize eager singleton - binding.collect { - case s@SingletonBinding(from, to, eager) if eager => - singletonHolder.getOrElseUpdate(to, buildInstance(to, Set(to))) - case InstanceBinding(from, obj) => - registerInjectee(from, obj) + private[inject] def init() = { + // Initialize eager singleton + binding.collect { + case s@SingletonBinding(from, to, eager) if eager => + singletonHolder.getOrElseUpdate(to, buildInstance(to, Set(to))) + case InstanceBinding(from, obj) => + registerInjectee(from, obj) + } } def get[A](implicit ev: ru.WeakTypeTag[A]): A = { @@ -89,6 +91,7 @@ private[inject] class SessionImpl(binding: Seq[Binding], listener: Seq[SessionLi newInstance(p.valueType, seen) } trace(s"Build a new instance for ${t}") + // Add TODO: enable injecting Session to concrete classes val obj = schema.constructor.newInstance(args) registerInjectee(t, obj) case None => diff --git a/wvlet-inject/src/test/scala/wvlet/inject/InjectTest.scala b/wvlet-inject/src/test/scala/wvlet/inject/InjectTest.scala index e4981f6d..904c53cd 100644 --- a/wvlet-inject/src/test/scala/wvlet/inject/InjectTest.scala +++ b/wvlet-inject/src/test/scala/wvlet/inject/InjectTest.scala @@ -16,7 +16,7 @@ package wvlet.inject import java.io.PrintStream import java.util.concurrent.atomic.AtomicInteger -import wvlet.log.LogSupport +import wvlet.log.{LogLevel, LogSupport} import wvlet.obj.ObjectType import wvlet.obj.tag.@@ import wvlet.test.WvletSpec @@ -131,6 +131,12 @@ object ServiceMixinExample { val initializedTime = System.nanoTime() } + trait EagerSingletonWithInject extends LogSupport { + info("initialized") + val heavy = inject[HeavyObject] + val initializedTime = System.nanoTime() + } + class ClassWithContext(val c: Session) extends FortunePrinterMixin with LogSupport { //info(s"context ${c}") // we should access context since Scala will remove private field, which is never used } @@ -217,6 +223,17 @@ class InjectTest extends WvletSpec { s.initializedTime should be < current } + "create single with inject eagerly" in { + val start = System.nanoTime() + val h = new Inject + h.bind[EagerSingletonWithInject].toEagerSingleton + val c = h.newSession + val current = System.nanoTime() + val s = c.get[EagerSingletonWithInject] + + s.initializedTime should be > start + s.initializedTime should be < current + } "found cyclic dependencies" in { val c = new Inject().newSession