views:

76

answers:

4

How we can manually inject an object without using the facility of containers. I did something similar through reflection as follows.

Class actionClass = Class.forName("SampleClass");
Object actionObject = actionClass.newInstance();
Method reqMethod = actionClass.getMethod("setRequest", HttpServletRequest.class);
reqMethod.invoke(actionObject,request);

is it the right way to do DI?

My intention is to pass request object to different controller classes dynamically from a dispatcher filter,where we get request and response objects. I am fearing about the performace of reflection.Is there any replacement for doing DI?

+1  A: 

Dependency Injection implies you get properly initialized references appearing "by magic".

You call the setRequest() method with the request object, but DI frequently also allows for setting the fields without invoking methods.

Guice does not as such require a container, but uses class loader magic started in the main method. Would that be useable for you?

Thorbjørn Ravn Andersen
I like the term "by magic". How the initialization is happening. How it is done in Spring or similar DI containers.
cdb
The idea is to move the initialization away from both the injected class and the class the injection happens in, so they don't know how it happens. Where you then move the injecting code to, is implementation dependent, and _you_ essentially don't need to know. In the end reflection is used but that is just like saying Hibernate is using JDBC in the end.
Thorbjørn Ravn Andersen
My intention is to pass request object to different controller classes dynamically from a dispatcher filter,where we get request and response objects.
cdb
By using reflection i am fearing about performance.If spring is doing the same way,then no i will do the same.
cdb
Reflection is the only way. When in doubt about performance, measure.
Thorbjørn Ravn Andersen
+2  A: 

Dependency injection is nothing more than providing a class with its dependencies, rather than have it find them itself (via singletons/lookups etc.). So you can do it in code trivially thus:

DatabaseConnection dc = new DatabaseConnection();
MyDAO dao = new MyDAO(dc);

(pseudocode). Here the MyDAO is being injected with a database connection. If that database connection implements an interface you can easily mock this out during testing.

Brian Agnew
+1  A: 

Well, when you set one object into another object using setter method or through a constructor it also is the dependency injection. Dependency injection only means creating relationship(dependency) in objects.

Using reflection as you did is just another form of it.

Gopi
A: 

Why would you use reflection? Why not simply:

SampleClass action = new SampleClass();
action.setRequest(request);

That does the same thing, but is more readable, allows the compiler to check that the types and methods actually exist, provides you with Javadoc for the Method invoked, enables your IDE to assist in refactorings, ...

And it still is dependency injection, because the action doesn't go looking for its request, but receives the request during initialization.

Edit: Thorbjørn requested I show how that action would be used. It would itself be injected (using a setter) into whatever component uses the action. The component would then use the injected action object.

SampleClass action = new SampleClass();
action.setRequest(request);
Servlet servlet = new ActionBasedServlet();
servlet.setAction(action);

If servlet is intended to live longer than action, i.e. it should use a fresh Action each time it needs one, one can instead setter-inject an ActionFactory into servlet.

In this concrete case, I'd question whether the action really needs to keep a request as part of its state, or can be immutable and simply act on the request passed by the Servlet as method parameter. In that case, the boot-time initialization would do:

SampleClass action = new SampleClass();
Servlet servlet = new ActionBasedServlet();
servlet.setAction(action);

and ActionBasedServlet would define

public void serve(Request req, Response resp) {
    foo();
    action.act(req, resp);
    bar();
}
meriton
The `new` keyword gives an extremely strong binding from the current class to the one new'ed. Dependency injection _decouples_ this strong binding between the two.
Thorbjørn Ravn Andersen
Dependency injection decouples the component from its dependencies. That doesn't mean that there must not be another part of the code knowing both the component and its dependency. SampleClass is not coupled to the particular request in my example.
meriton
In my case, the classname is dynamic.To make a common DI for all classes. ie why i used reflection. thanks for your answer.
cdb
@meriton, in that case please add the extra code showing how to _use_ the action object.
Thorbjørn Ravn Andersen