Reputation: 705
I am trying to use Guice and I am coming from Spring.
I am wondering if @Inject
is the equivalent of @Autowired
in Spring and if I can use it in web application exactly as I am using it in Spring.
Imagine I have a Facade which depends on a service, in Spring I can define a bean for that service and then when the server starts up I can get the instance of the service inside my facade.
class FacadeImpl{
@Autowire Service service;
...
}
Assume that service has a concrete implementation and in Spring will automatically inject it.
Does Guice has a similar approach? can I do something like
class Facade{
@Inject Service service;
}
or is it a magic that only spring does?
In my web application, I am starting embedded tomcat and I used google guice modules in such a way
Guice.createInjector(new ConfigurationModule());
hoping that this will be enough to "inject" whatever is annotated with @Inject
.
However, it is not working ( I am not surprised ). Can you guys help me to figure out which are the BP to inject dependencies on my Servlets or Facades etc..?
Upvotes: 2
Views: 4748
Reputation: 35427
@Inject
can act as @Autowired
... given some conditions.Guice doesn't require Module
s, though they're very often used. So you can get rid of them if you want to.
If your class is a concrete class, you can directly @Inject
it, just like @Autowired
, but you also probably have to mark the class @Singleton
because the default scope in Guice is not singleton, but a new instance everyone, unlike Spring.
Guice is not Spring, but the most important features of one are present in the other.
When you want to use Guice with Tomcat, there is very little configuration to do, but there is still configuration. You will require a Module
, but only the servlet.
In your web.xml
, add the following:
<listener>
<listener-class>path.to.MyGuiceServletConfig</listener-class>
</listener>
<filter>
<filter-name>guiceFilter</filter-name>
<filter-class>com.google.inject.servlet.GuiceFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>guiceFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
MyGuiceServletConfig.java
public class MyGuiceServletConfig extends GuiceServletContextListener {
@Override protected Injector getInjector() {
return Guice.createInjector(new ServletModule() {
@Override protected void configureServlets() {
serve("/*").with(MyServlet.class); // Nothing else is needed.
}
});
}
}
MyServlet.java
public class MyServlet extends HttpServlet {
@Inject // Similar to @Autowired
private MyService myService;
@Override public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
resp.getWriter().write(myService.hello("Guice"));
}
}
Now you have a choice with MyService
: either you make an interface out of it and you have to define, and bind an implementation, or you make a concrete class out of it.
MyService
as an interfaceMyService.java
@ImplementedBy(MyServiceImpl.class) // This says "hey Guice, the default implementation is MyServiceImpl."
public interface MyService {
String hello(String name);
}
MyServiceImpl.java
@Singleton // Use the same default scope as Spring
public class MyServiceImpl implements MyService {
// @Inject dependencies as you wish.
public String hello(String name) { return "Hello, " + name + "!"; }
}
If you want to avoid the @ImplementedBy
, you can still use your module above, and add bind(MyService.class).to(MyServiceImpl.class).in(Scopes.SINGLETON);
, or write a provider method in the same Module
:
@Provides @Singleton MyService provideMyService() {
return new MyServiceImpl();
}
MyService
as a concrete classMyService.java
@Singleton // Use the same default scope as Spring
public class MyService {
// @Inject dependencies as you wish.
public String hello(String name) { return "Hello, " + name + "!"; }
}
Upvotes: 2
Reputation: 62535
In Guice, there is no direct equivalent of the @Autowired
Spring annotation. Dependency injection usage is explained in the Getting started page.
1) You have to annotate the constructor of your service with the @Inject
annotation:
@Inject
BillingService(CreditCardProcessor processor,
TransactionLog transactionLog) {
this.processor = processor;
this.transactionLog = transactionLog;
}
2) Then define the bindings between types and implementations in a module:
public class BillingModule extends AbstractModule {
@Override
protected void configure() {
/*
* This tells Guice that whenever it sees a dependency on a TransactionLog,
* it should satisfy the dependency using a DatabaseTransactionLog.
*/
bind(TransactionLog.class).to(DatabaseTransactionLog.class);
/*
* Similarly, this binding tells Guice that when CreditCardProcessor is used in
* a dependency, that should be satisfied with a PaypalCreditCardProcessor.
*/
bind(CreditCardProcessor.class).to(PaypalCreditCardProcessor.class);
}
}
3) And finally build an injector and use it:
public static void main(String[] args) {
/*
* Guice.createInjector() takes your Modules, and returns a new Injector
* instance. Most applications will call this method exactly once, in their
* main() method.
*/
Injector injector = Guice.createInjector(new BillingModule());
/*
* Now that we've got the injector, we can build objects.
*/
BillingService billingService = injector.getInstance(BillingService.class);
...
}
Upvotes: 1