In Guice, when you indicate the lifetime of a certain instance, you will use a scoping annotation like bind(Applebees.class).in(Singleton.class);.
Or you appear to be able to use scope instances like
bind(UserPreferences.class)
.toProvider(UserPreferencesProvider.class)
.in(ServletScopes.REQUEST);
And officially Guice recommends the former approach because the former approach allows us to reuse the Module class.
But I am not sure of the point. My assumption is like this, so please check if this is right.
Scope instances is the term of Servelet, so if you adopt scope instances instead of scoping annotations, the Module class is only applicable to the Servelet. On the other hand, if you use scoping annotations, you can reuse your Module class unless you abandon Guice.
So, is this right? Could you check?
I believe your understanding is correct, but there's a little subtlety about what kind of reuse would be affected.
You're probably referring to this text from the Guice wiki on Scopes (emphasis mine):
The in() clause accepts either a scoping annotation like RequestScoped.class and also Scope instances like ServletScopes.REQUEST:
bind(UserPreferences.class)
.toProvider(UserPreferencesProvider.class)
.in(ServletScopes.REQUEST);
The annotation is preferred because it allows the module to be reused in different types of applications. For example, an #RequestScoped object could be scoped to the HTTP request in a web app and to the RPC when it's in an API server.
Even with Guice's servlet-specific scopes, you can choose between the Scope instance ServletScopes.REQUEST and the #RequestScoped annotation, and choose between in(Scope scope) and in(Class scopeAnnotation) accordingly (see ScopedBindingBuilder). Nearly every scope should have a corresponding annotation, as they are especially useful on classes and #Provides methods.
It's important to realize here that there's always a Scope instance that actually implements the scoping behavior (specifically, wrapping an unscoped Provider so that it can return already-returned instances in the right conditions). To associate an annotation to a Scope instance, you need to make sure that a module calls bindScope, which accepts the Scope annotation class and the Scope instance; for Servlets, Guice has this binding automatically installed via InternalServletModule.
#Override
protected void configure() {
bindScope(RequestScoped.class, REQUEST);
bindScope(SessionScoped.class, SESSION);
// ...
}
So what's the advantage of using in(Class scopeAnnotation)? When binding to a Scope instance, you are telling Guice exactly which Scope instance you want to use, rather than allowing the user an opportunity to use bindScope to bind the annotation to a different Scope instance. In the example I bolded above, you can imagine using the same Module without using the actual Guice servlet extensions (other than the annotations), but this would only be possible if you bind to annotation classes and then call bindScope yourself. If you bind using in(Scope), you'll need to change that line or write a new Module.
This is especially important for your own custom Scope instances and annotations, because it allows you to change your Scoping behavior consistently across your application:
#Override public void configure() {
// BAD: To change the scope, you'll need to change three lines.
// If you don't change all three together, you'll get inconsistent behavior.
bind(A.class).to(AImpl.class).in(MyScope.INSTANCE);
bind(B.class).to(BImpl.class).in(MyScope.INSTANCE);
bindScope(AScoped.class, MyScope.INSTANCE);
}
#Override public void configure() {
// GOOD: To change the scope, you can change one line, and optionally
// extract that line to a separate Module.
bind(A.class).to(AImpl.class).in(AScoped.class);
bind(B.class).to(BImpl.class).in(AScoped.class);
bindScope(AScoped.class, MyScope.INSTANCE);
}
Related
I am trying to apply ioc into a school project. I have an abstract class Application without any field
public abstract class Application {
abstract public void execute(ArrayList<String> args, OutputStream outputStream, InputStream inputStream) throws IOException;
}
And I will call the concrete class that extends Application by
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
Application app = (Application)context.getBean(appName);
My questions are:
Is it a bad practice to initialise a bean without any field (or all the fields are constants) using Spring?
As there is no dependency to other classes in Application, are we still consider this as a dependency injection or IOC? If no, what is the difference between this and a normal factory pattern? It seems that what Spring does here is simply matching the class and initializing it.
UPDATE
Here is the code snippet of the class where the instance of Application is needed.
String appName = argument.get(0);
Application app = ApplicationFactory.getApplication(appName);
ArrayList<String> appArgs
= new ArrayList<String>(argument.subList(1, argument.size()));
app.execute(appArgs, outputStream, inputStream);
Further questions:
in my code the class X will call the instance of Application by specifying a concrete application class name. In this case, it is still not possible for Spring to inject the dependency to Application, right? As what I need is a concrete class but not Application itself.
if Application does have fields but these fields are initialsed somewhere higher than X (X receives them as inputs and passes them to Application), can I use DI in this case?
Is it a bad practice to initialise a bean without any field (or all the fields are constants) using Spring?
No, its totally fine. Its true that you won't be able to "take advantage" of the automatic dependency injection mechanisms provided by spring (because obviously there are no dependencies in the class Application in your example), however spring can still:
Make sure that the Application as a singleton "obeys" the rule of being a single instance in the whole application context. For "manually" maintaining singletons you need to write code. Spring does it for you.
Manages the lifecycle of the object. Example, Spring has "postConstruct"/"preDestroy" methods that can can be run in the appropriate time and make example any custom code of the class Application.
If this class does some heavy-lifting (even without spring) than it can make sense to define it "lazy" so that the initialization of this instance will actually be done upon the first request to it.
Sometimes you/or spring itself will create a proxy of this class in runtime (for many different reasons, for example this aforementioned lazy functionality, but there are also other use cases). This is something that spring can do for you only if it manages the Application and not if its defined outside the spring.
Ok, you don't have dependencies in the application, This means that this Application class has some useful methods (at least on method, like public void foo() for
simplicity). But this in turn means that there is some class (lets call it X) that calls this method. So this class has an instance of Application as a dependency. So now the real question is who manages this class X. Probably it makes sense to manage it in Spring as well, and then you will benefit of the Dependency Injection mechanisms in this class X only because Application is also managed by Spring. In general Spring can inject dependencies only if these dependencies are managed by Spring.
I know, this last paragraph may sound vague given the use case you've presented, but you've got a point, for example in real application people make an initial bootstrapping in very certain places. Usually also people use spring boot that kind of encapsulates this kind of things for you.
As there is no dependency to other classes in Application, are we still consider this as a dependency injection or IOC? If no, what is the difference between this and a normal factory pattern? It seems that what Spring does here is simply matching the class and initializing it.
So as you see, the concept of DI container goes far beyond of what the factory pattern has to offer. In short, factory pattern only specifies the way to create the objects. Spring on the other hand, not only creates the objects but also manages them.
First, I very strongly suggest that you use Spring Boot instead of manually manipulating Spring at a low level like this.
It's perfectly ordinary to use beans that don't have their own fields for settings, but this is usually so that other beans can have pluggable strategies or providers and you can define in your application setup which to use.
If your Application class doesn't need anything else, then there really is not much advantage to Spring. Most real-world programs get complicated soon, however, and that's where it becomes useful.
Finally, you should almost never pass ArrayList as a parameter; use List instead. In the code you showed, however, if you have String[] args, you couldn't say app.execute(Arrays.asList(args), System.out).
So I'm implementing a Dependency Injection framework into my Java project (Google Guice) and everything is pretty good, I like it but there's a small problem;
I want to make a static instance of my main project's class (where it instantiates the dependencies, etc). But I don't know any method to instantiate it using Guice, I can't instantiate it manually because I'm using DI in the constructor of it (I have objects in the constructor) which means that I am not able to access the class' non-static variables needed to instantiate the class.
I tried using a Provider but I couldn't really understand where to bind it, because I don't want to have an interface for the main class (will if needed).
If you are wanting to mix a static instance of a class with dependency injection, you have somewhat missed the point of dependency injection: you can simply inject the instance of the class.
If you want there to be a single instance of a class for your injector, bind it in #Singleton scope: either:
bind(YourClass.class).in(Singleton.class);
in your module's configure() method, or
#Provides #Singleton YourClass provideYourClassInstance() {
// ...
}
in your module, or
#Singleton class YourClass {
// ...
}
in the actual class declaration.
Then just inject this instance like any other:
class SomeOtherClass {
#Inject SomeOtherClass(YourClass instance) {
// ... Do something with instance, like assign it to a field.
}
}
The point is that SomeOtherClass shouldn't need know anything about the lifetime of instance: it simply doesn't matter whether this is a singleton instance, or every class using it has its own instance.
You can get three different answers here depending on the question.
To directly answer the question in the title (DI with arguments in the constructor), you can mix DI with constuctor arguments by instead injecting a Factory. Though you're welcome to write one manually, Guice can do this for you as assisted injection (see FactoryModuleBuilder), or you can use the equivalent code-generated solution AutoFactory popular through Dagger.
If you're trying to initialize a static class's fields in a Guice application, Guice can do that for you as soon as the Injector is created. Simply call requestStaticInjection in a Module you feed to Guice. This, as Andy Turner pointed out, will cause you to miss out on some of the benefits of Guice: Because you're injecting the instance statically, there's very little opportunity for you to provide replacement implementations in tests or in other class reuse. Guice describes this more in the static injections section of its wiki:
When migrating an application from static factories to Guice, it is possible to change incrementally. Static injection is a helpful crutch here. It makes it possible for objects to partially participate in dependency injection, by gaining access to injected types without being injected themselves. [...]
Static members will not be injected at instance-injection time. This API is not recommended for general use because it suffers many of the same problems as static factories: it's clumsy to test, it makes dependencies opaque, and it relies on global state.
The best overall solution is in Andy's answer: Adapt your application to use DI, which will let it inject the objects that you would otherwise make static.
I have a question:
Usually in Guice I use bind(classe).to(another_class_Implementation) ...
However I found in a code source that they have used bind(class) only ( without the part ".to(another_class_Implementation)" ) ...
What does this mean ( bind(class) without "to or as" ) ?
Here is the part of code in question:
public class RestModule extends AbstractModule {
#Override
protected void configure() {
bind(RootResource.class);
bind(DeveloperUtilsRedirector.class);
bind(M34Repository.class).to(M34RepositoryImpl.class);
bind(IGARepository.class).to(IGARepositoryImpl.class);
Answers are appreciated
A bind statement without a to is called an Untargeted Binding (misspelled as "Untargetted Bindings" in the wiki URL) in the Guice docs. From that wiki page:
You may create bindings without specifying a target. This is most useful for concrete classes and types annotated by either #ImplementedBy or #ProvidedBy. An untargetted [sic] binding informs the injector about a type, so it may prepare dependencies eagerly.
You'll see this in Guice for three purposes:
Slight performance improvement via eager loading.
When Guice encounters a dependency that it doesn't have a binding for (say, class A), it inspects the class to see if it can be injected via an #Inject-annotated or zero-arg public constructor. If so, Guice creates a Just-In-Time binding (or "implicit binding"). This is done through reflection, and may cause a cascade of other bindings (requesting A inspects A, then A's dependency B, then B's dependency C, and so forth), which can cause some runtime slowdown.
By pre-emptively making an untargeted binding, you inform Guice about an injectable class, which allow it to pay that reflection cost at startup for more predictable performance.
Guice will throw an exception if it cannot create the object you inject, but in the case of #ImplementedBy or #ProvidedBy (or getInstance or injectMembers) Guice will not fail if it hasn't inspected the class with the missing binding yet. By listing classes you use, Guice will pre-analyze those objects as in (1), but will also recognize at app startup that a binding is missing. This may be handy during development, especially if you are injecting an object with getInstance or injectMembers long after application startup; you might prefer that failure to happen immediately.
Though implicit bindings are enabled by default, they can be disabled through requireExplicitBindings. This means that any injected classes need to have associated bindings, including classes with eligible constructors. An untargeted binding would resolve that situation easily.
This question is a continuation of Using guice for a framework with injected classes, proper way to initialize?, which I've tried to implement, and also tried other ways to get around the issue, but nothing has worked so far.
The main issue is this. I have an InterfaceA and InterfaceB that are exposed in different parts of the API. There are two classes that implement both of these interfaces, TestClass and RealClass, so that depending on whether I'm testing or doing something else, I can do the following:
bind(InterfaceA.class).to(TestClass.class);
bind(InterfaceB.class).to(TestClass.class);
or, for production:
bind(InterfaceA.class).to(RealClass.class);
bind(InterfaceB.class).to(RealClass.class);
I have two requirements for using these classes:
I need the same instance of TestClass or RealClass to be bound to all injections of InterfaceA and InterfaceB; so, like a singleton pattern, except that:
The singleton is only for a specific scope or child injector, many of which are created during the execution of the program.
The default no-scope approach causes multiple instances of RealClass/TestClass to be created for each interface injection. I don't want that, so I've tried implementing this with scopes, child injectors, and other methods. Nothing has worked:
Child injector approach: I create a new injector and try to bind the TestClass or RealClass to a singleton instance in that injector. The problem is, whether TestClass or RealClass is being used is configured in the parent injector, and since it's a singleton, it's already instantiated (unless in Stage.DEVELOPMENT). There's no way to bind InterfaceA to TestClass, in the parent injector, for example, and then re-bind it as a singleton in the child injector.
Scope approach: I create a custom scope and annotate TestClass and RealClass. Then, I enter and exit this scope to get single instances in that scope. The problem is that my code is multithreaded and having the scope change from one thread affects what the global injector can see and mucks up creating other instances.
Combined child injector and scope approach. I tried creating a child injector for each use of this custom scope, but then binding RealClass in the parent fails with
No scope is bound to name.package.WhateverScope.
because it seems to insist that the WhateverScope is available all the time, not just in the child injector.
All these problems seem to be due to the fact that I need to be able to configure whether to use TestClass or RealClass in the parent, but then to be able to instantiate them later, as a singleton, for a specific group of objects. I'm pulling my hair out over how to get this done!
By the way, the documentation for Guice scopes is horrible and almost impossible to understand. This article is the only one that has gotten me anywhere:
Apologies for a somewhat-breakthrough less than an hour after posting.
I seem to have been able to fix this by somewhat abusing the thread-local scope implementation provided at http://code.google.com/p/google-guice/wiki/CustomScopes. It seems to be a somewhat clean way to solve this problem without using child injectors. I'm not sure if it's 'proper', though. I'll still accept other answers.
Here's what I did. First, I create one instance of the scope, bind it to the appropriate annotation, and make it available in the injector:
ThreadLocalScope scope = new ThreadLocalScope();
bindScope(ExperimentScoped.class, scope);
bind(ThreadLocalScope.class).toInstance(scope);
Then, as the documentation says, I need to bind a fake provider for every type of key that would be seeded in the scope:
bind(SomeKey.class)
.toProvider(ThreadLocalScope.<SomeKey>seededKeyProvider())
.in(ExperimentScoped.class);
bind(SomeOtherKey.class)
.toProvider(ThreadLocalScope.<SomeOtherKey>seededKeyProvider())
.in(ExperimentScoped.class);
I may also have some other scope-able objects that I want to be distinct within each scope, so I bind those too. These are the TestClass and RealClass above. There may be also SomeScopedClass that was annotated with the #ExperimentScoped:
bind(InterfaceA.class).to(TestClass.class).in(ExperimentScoped.class);
bind(InterfaceB.class).to(TestClass.class).in(ExperimentScoped.class);
bind(SomeInterface.class).to(SomeScopedClass.class);
Finally, I can use the scope to create distinct sets of interdependent objects, in parallel from different threads. Each thread can do something like the following, even though they are using the same injector:
ThreadLocalScope scope = injector.getInstance(ThreadLocalScope.class);
scope.enter();
try {
// Seed the seed-able keys
scope.seed(SomeKey.class, keyInstance);
scope.seed(SomeOtherKey.class, otherKeyInstance);
SomeScopedClass instance = injector.getInstance(SomeScopedClass.class);
// Hooray! instance was injected with the seeds and created just for this scope!
}
finally {
scope.exit(); // Throws away the scope and referenced objects.
}
In my case, I can discard the scope completely because I don't care about keeping track of the set of objects in the scope once they're wired up properly. But it probably wouldn't work if I wanted to come back to this scope later and inject some more objects.
Hope this helped someone. The Guice scoping documentation is terrible!
I'm having some troubles understanding how Guice's singleton instantiations works. I've read the available documentation (here - http://code.google.com/p/google-guice/wiki/Scopes ), but I still can't figure out some things:
I've integrated Guice with Tomcat, and I've set up some bindings in a ServletModule:
bind(MyServlet.class).asEagerSingleton();
serve("myUrl").with(MyServlet.class);
serve("myOtherUrl").with(MyOtherServlet.class);
(where MyOtherServlet class has a #Singleton annotation above it)
My intention here was to have two servlets, where one is eagerly instantiated, while the other isn't. However it seems like the "serve... with..." line automatically instantiates servlets objects, even though that class is not bound as an eager singleton.
The link I attached above mentions difference between Guice running under Stage.Development and Stage.Production - however this still happened even when I explicitly used Stage.Development (which is the default one anyway).
Is there any way to avoid this?
(continues 1) Trying to ensure that MyServlet gets instantiated first even though all servlets instantiate eagerly now, I've modified the order of modules (and binding statements) when creating an Injector, so that the binding for MyServlet appears first. However, I found that it still gets instantiated later than some other bindings (of non-servlet classes), which were of the form:
bind(MyInterface.class).to(MyClass.class).asEagerSingleton()
even though those other bindings appeared later in the modules/bindings order.
I've looked into it, and found that Guice simply instantiates eager singletons which were bound by the form of "bind... to... asEagerSingleton()" before it does ones of "bind... asEagerSingleton()", and so I solved it by modifying the line:
bind(MyServlet.class).asEagerSingleton();
into:
bind(MyServletDummyInterface.class).to(MyServlet.class).asEagerSingleton()
and that actually worked. Still, I'd rather avoid having a dummy interface just to solve this, so I was wondering if anyone had a better solution for this..?
I have two Guice modules - one ServletModule and one AbstractModule.
The ServletModule configureServlets() has the following binding in it:
serve("aUrl").with(SomeServlet.class);
The AbstractModule's configure() has the following bindings:
bind(SomeImpl.class).asEagerSingleton();
bind(SomeInterface.class).to(SomeImpl.class).in(Singleton.class);
Additionally, The SomeServlet class has an injected field of type SomeInterface, and has a #Singleton annotation on top of the class.
Now, one would expect that upon creating an injector, the SomeImpl class will get instantiated, and the same instance will be injected into the SomeServlet instance. As mentioned before, servlets bounded with a "serve... with..." statement also seem to get eagerly instantiated, but either way there should still be only one SomeImpl object instantiated. Yet for some reason, I got two SomeImpl objects instantiated when doing this.
To get around it, I mixed the two lines in configure() a bit, and instead of the above I had there the following lines:
bind(SomeImpl.class).in(Singleton.class)
bind(SomeInterface.class).to(SomeImpl.class).asEagerSingleton();
and then it worked fine, and I got only one instance of SomeImpl instantiated. I don't really get why the switch should matter - I can see how the latter way is "better", but I'd expect both to work correctly, so I'm just wondering if I'm getting something wrong here...
1) There is no way to avoid this, since Guice calls the init() method of all servlets on initialization of its own filter pipeline and thus constructs them all. If you really need such lazy initialization logic, you should place it into the servlet itself (or use a decoupled helper class, or... there are many ways, depending on your use case).
2) Generally said, the modules of Guice declare bindings, there are not designed to be bootstrap definitions with precise instantiation orders. If you need such a defined instantiation order, create the objects yourself in the desired order and bind them via bind(...).toInstance(...). If you need injection in the self constructed instances you may use requestInjection(...) (if field/method injection is sufficient, it's more cumbersome for constructor injection).
3) The scope of Guice applies to the binding key, not the binding value, Applying Scopes describes why only your second example is working as intended.