Can someone explain what com.google.inject does?
Asked Answered
G

1

11

I've seen a class declared with its only constructor being annotated with @Inject. And I don't see the one constructor being called anywhere in the entire project.

So two questions:

  1. What does @Inject mean? (What does it do? Why is the constructor being annotated with it?)
  2. As mentioned, the constructor never gets called directly, does that have anything to do with the fact that it is annotated with @Inject?
Gothart answered 20/3, 2013 at 22:22 Comment(1)
That class belongs to the Guice library. Which is itself an Inversion of Control framework.Recommit
T
15

Google Guice is a dependency injection library that allows you to construct objects simply by declaring relationships between them. Objects are constructed as they are demanded to construct other objects. You can also implement abstract classes or interfaces with different implementations by configuring Guice, which makes it very useful for running or testing your code.

@Inject annotates constructors and methods that determine what an object needs to be initialized. There are also a lot of other annotations that determine how Guice works. But simply annotating objects isn't enough; you also have to configure them with Guice bindings.

Here's a really simple example (from one of my applications). I have a MySQLDataTracker that requires a MysqlConnectionPoolDataSource:

public class MySQLDataTracker extends ExperimentDataTracker {
    @Inject
    public MySQLDataTracker(MysqlConnectionPoolDataSource ds) {
        ....
    }
}

Note that MySQLDataTracker extends ExperimentDataTracker, an abstract class that can be implemented several ways. In my Guice bindings I declare that

bind(ExperimentDataTracker.class).to(MySQLDataTracker.class);

This declares that whenever I want an ExperimentDataTracker, a MySQLDataTracker will be constructed. I also need to make sure that the requisite object for constructing this is available, so I declare a provider:

@Provides @Singleton 
MysqlConnectionPoolDataSource getMysqlCPDS() {
    return (some thingy I construct...);            
}

This says that there should only be a single connection pool data source. It also means that when I try to get an instance of ExperimentDataTracker, Guice has everything it needs to construct it. If I didn't have the above, it would throw an error.

ExperimentDataTracker tracker = injector.getInstance(ExperimentDataTracker.class);

However, it doesn't stop here. Other things depend on the ExperimentDataTracker, so it's used in turn to inject other objects. At the top level of my code there is actually only one call to getInstance, which makes Guice construct pretty much everything. I don't have to write the new statement anywhere.

I'm a big fan of Guice after seeing how it reduced the need for me to initialize a bunch of objects in order to initialize other objects. Basically I just ask for the object I want, and poof! it appears.

Tithable answered 20/3, 2013 at 22:30 Comment(5)
So if I change the constructor's formal parameter, where else would I need to change to make sure it is called properly? (Where would you suggest I look to update the 'call' to the constructor?)Gothart
If you run the application with Guice, you will get errors if something can't be injected. That's the best way to check. :) Also, unit testing with mock objects constructed manually.Tithable
Do you mind briefly explaining how an object could be constructed without its constructor being called? Is there some config file or something where one lists a bunch of constructor's parameters? (Sorry, I'm a newbie and I really have a hard time understanding this)Gothart
Yes, I expanded a bit. To answer specifically, Guice calls the constructors using reflection. But you should really read the docs to get an idea of how it's used. Dependency injection is very powerful and worth learning, as it can save you a lot of work and refactoring.Tithable
I think I understand it a bit better now. Thank you.Gothart

© 2022 - 2024 — McMap. All rights reserved.