The basic idea behind dependency injection with VRaptor is to inject objects in your business components.
public class DaoFactory { public PersonDao getPersonDao() { return new PersonDao(); } public StudentDao getStudentDao() { return new StudentDao(); } }
Note: The @Out annotation is used to outject the factory field to the request scope...
public class DaoInterceptor implements Interceptor { @Out private DaoFactory factory = new DaoFactory(); public void intercept(LogicFlow flow) throws LogicException, ViewException { // executes the next interceptor or business logic flow.execute(); } }
@Component("injection") @InterceptedBy(DaoInterceptor.class) public class InjectionExample { @In private DaoFactory factory; public void test() { // do something with the injected factory } }
If you call injection.test.logic the following flow gets executed:
Instantiate Interceptor --> Calls intercept method --> Interceptor calls flow.execute --> Outjects the dao factory --> Instantiate Bussiness Component --> Injects the dao factory --> Read parameters --> Call Logic method --> Redirects to view page Finishes the intercept method
The injection uses by default the request scope. You can use the same scopes as the @Out annotation: see ScopeType.
VRaptor supports constructor injection by looking for objects in all scopes. For example:
public class InjectionExample { private DaoFactory factory; public InjectionExample(DaoFactory factory) { this.factory = factory; } public void test() { // do something with the injected factory } }
If DaoFactory is contained in the package org.vraptor.dao, then VRaptor looks for the key org.vraptor.dao.DaoFactory in all scopes: logic, request, session and application, in this order.
If it does not find this key in any scope, its unable to instantiate your component and will throw an Exception.
Otherwise it uses the key value to pass as an argument to the constructor.
No component can have more than one constructor available, otherwise you would be able to create complex and strange components with potential bugs.
In order to make the above example with constructor injection to work, simply use the following interceptor:
public class DaoInterceptor implements Interceptor { @Out(key="org.vraptor.dao.DaoFactory") private DaoFactory factory = new DaoFactory(); public void intercept(LogicFlow flow) throws LogicException, ViewException { // executes the next interceptor or business logic flow.execute(); } }
You can get direct access to the four basic contexts through constructor injection. Simply add your constructor as:
public MyLogicConstructor(HttpServletRequest request) { this.request = request; }
And leave the request as a member variable. Do whatever you want with it!
You can also grab it through the usual @In annotation:
@In private HttpServletRequest request; @In private HttpServletResponse response; @In private HttpSession session; @In private ServletContext servletContext;