Search code examples
scalaguice

How to inject Scala classes in objects?


I want to use a singleton class in a Scala companion object but I am using Guice dependency injection and, as far as I know, it has no explicit usage in these scenarios.

As an example, let's say we have Singleton (using Guice) class as follows:

@Singleton
class Foo Inject()(foo2: Foo2) { 
    def func = { ... }
}

I can use it in other classes as:

class MyClass Inject()(foo: Foo) { 
   foo.func()
}

What about objects? I need to create an instance with new as:

object MyObject { 
   val foo2 = new Foo2()
   val foo = new Foo(foo2)
   foo.func()
}

In this case, does Foo still have just one instance? I mean, does new Foo(foo2) return the same instance as Guice returns in @Inject()(foo: Foo)?

By the way, there are already questions about this (e.g., link) but I want to use objects and access the singleton instances inside them.


Solution

  • In this case, does Foo still have just one instance? I mean, does new Foo(foo2) return the same instance as Guice returns in @Inject()(foo: Foo)?

    No. Just as if you call new Foo(...) elsewhere. My suggestion would just be not to mix it; if you want to use Guice's instances inside MyObject, make it a Guice singleton class as well. Or make Foo an object, you can still access it from Guice-using classes.

    If you really need it, the way I can think of is really ugly; to store the Injector from your main (or wherever you create it) somewhere MyObject can access it, i.e.

    object Main {
      var injector: Injector = null
    
      def main(args: Array[String]): Unit = {
        // make sure this happens before MyObject is accessed
        injector = Guice.createInjector(...)        
        ...
      }
    }
    
    object MyObject { 
      val foo = Main.injector.getInstance(classOf[Foo])
      foo.func()
    }
    

    If you don't even create the Injector yourself, but are using some framework which uses Guice, check if it gives you access to the Injector.