2010-08-21 111 views
6

我们如何在不使用容器的情况下手动注入对象。我通过反思做了类似的事情,如下所示。如何手动实现依赖注入?

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

这是DI的正确方法吗?

我的目的是通过请求对象不同控制器类动态地从一个调度员过滤器,在那里我们得到请求和响应对象。 我很担心反射的表现。是否有替代做DI的替代品?

回答

0

依赖注入意味着你得到正确的初始化引用出现“魔术”。

与您通话请求对象了setRequest()方法,但DI经常也允许设置字段而不调用方法。

Guice并不像这样需要一个容器,而是使用主要方法启动的类加载器魔术。这对你有用吗?

+0

我喜欢“魔术”这个词。初始化如何发生。它是如何在Spring或类似的DI容器中完成的。 – 2010-08-21 10:08:15

+1

这个想法是将注入的类和注入发生的类从初始化中移走,所以他们不知道它是如何发生的。然后将注入代码移到哪里,取决于实现,而_you_本质上不需要知道。最后使用了反射,但这就像说Hibernate最终使用JDBC一样。 – 2010-08-21 10:29:30

+0

我的意图是将请求对象从调度程序过滤器动态地传递给不同的控制器类,在那里我们获取请求和响应对象。 – 2010-08-21 11:07:34

5

依赖注入无非是提供一类具有它的依赖,而不是把它找到他们自己(通过单身/查找等)等等。所以你可以这样简单代码:

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

(伪代码)。这里MyDAO被注入一个数据库连接。如果该数据库连接实现了一个接口,则可以在测试过程中轻松地将其剔除。

2

那么,当你设置一个对象为使用setter方法或通过构造另一个对象,也就是依赖注入。依赖注入只意味着在对象中创建关系(依赖关系)。

像你这样使用反射只是它的另一种形式。

1

为什么要使用反射?为什么不干脆:

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

,做同样的事情,但更具有可读性,使编译器检查的类型和方法确实存在,为您提供Javadoc文档调用该方法,使您的IDE协助重构,...

它仍然是依赖注入,因为动作不去找它的请求,但在初始化过程中接收请求。

编辑:Thorbjørn要求我说明如何使用该动作。它本身会被注入(使用setter)到任何使用该动作的组件中。该组件将使用注入的操作对象。

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

如果servlet旨在活得比action,即它应该使用它需要一个新的Action每一次,一个可以代替setter方法注入的ActionFactoryservlet

在这个具体的例子,我会质疑行为是否真的需要保持一个请求作为其状态的一部分,也可以是不可变的,只是作用于由Servlet作为方法参数传递的请求。在这种情况下,引导时初始化会做:

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

ActionBasedServlet将定义

public void serve(Request req, Response resp) { 
    foo(); 
    action.act(req, resp); 
    bar(); 
} 
+0

'new'关键字从当前类到新类都提供了非常强大的绑定。依赖注入_将两者之间的这种强有力的约束联系起来。 – 2010-08-21 10:31:43

+3

依赖注入将组件从其依赖关系中分离出来。这并不意味着代码的另一部分不能知道组件及其依赖关系。在我的例子中,SampleClass没有耦合到特定的请求。 – meriton 2010-08-21 10:38:00

+0

在我的情况下,类名是动态的。为所有类创建一个通用的DI。即为什么我使用反射。感谢您的回答。 – 2010-08-21 11:03:26

0

Spring框架是最流行的DI实现之一。它也是开源的。 有关如何执行此操作的示例,可以查看org.springframeowrk.beans.BeanUtils类,特别是方法copyProperties(全部4个)。 欲了解更多信息,你还可以看到不同策略org.springframework.beans.factory.BeanFactory的类层次结构。