使用注解来注入依赖项是否会削弱依赖注入(外部配置)的主要优势?

6

我正在使用Spring,这是一个控制器:

@Controller
public class PersonController {

@Resource(name="PersonService")
private PersonService personService;

    @RequestMapping(value = "/Person", method = RequestMethod.GET)
    public String getPersons(Model model) {

    // Retrieve all persons by delegating the call to PersonService
    List<Person> persons = personService.getAll();

    // Attach persons to the Model
    model.addAttribute("persons", persons);
    //then return to view jsp       
}

这里是一个服务:

@Service("personService")
@Transactional
public class PersonService {

    public List<Person> getAll() {
        //do whatever
       }
}

然而,要正确使用 DI ,我应该更改控制器以使用接口(?)如下:

@Controller
public class PersonController {

@Resource(name="personService")
private IPersonService personService; //Now an interface
}

这将使我能够使用两个服务,一个测试,一个正式。通过添加/删除服务上的注释,我可以进行修改:
@Service("personService") // this line would be added/removed
@Transactional
public class LivePersonService implements IPersonService {

    public List<Person> getAll() {
        //do whatever
       }
}

而且
@Service("personService") //this line would be added/removed
@Transactional
public class TestPersonService implements IPersonService {

    public List<Person> getAll() {
        //do something else
       }
}

然而,由于代码需要重新编译,其中一个主要的好处被失去了。如果我使用XML查找,我可以即时更改依赖关系。


我不认为将其列为 DI 的重要优势,我认为这只是一种好处,或许更多的是锦上添花。 - skaffman
这将是相当主观的 - 有些人喜欢外部XML配置,有些人喜欢注释的相对简洁性。没有人是“正确”的。 - matt b
@skaffman,还有哪些其他重要的好处? - NimChimpsky
@NimChimpsky:DI 主要的好处,即从外部注入依赖项,而不是代码去获取它。 - skaffman
@skaffman,好的,那依赖注入还有哪些实际的好处可以应用到日常编码中呢?我可以看出根据你的配置(live、test、customer)查找不同服务的好处。除此之外还有什么? - NimChimpsky
@NimChimpsky:这已经涉及到“新问题”的领域了,而且SO上有很多关于这个问题的先前问题。此外,http://en.wikipedia.org/wiki/Dependency_injection。 - skaffman
3个回答

4
配置仍然是外部的,因为它在你定义将要被注入的实现的位置之外。在类内部,你只需要硬编码类所依赖的某个东西的名称(这是可以的,因为这种依赖是固有于该类的)。
也就是说,你可以使用 XML 来覆盖代码中的注释以进行测试执行(你将拥有一个特定的 XML 应用程序上下文用于测试),并指定将要注入哪个实现。
因此,你不需要更改你的代码来运行测试。请参见 this answer

2

没错,注解是源代码中的配置。主要用于每个服务都有一个类的情况。如果您有多个实现特定接口的选项,则XML将是更好的选择。此外,您可以混合使用XML配置和注解。


0

传统的方法,我上次从 DI 训练营听到的是,在单元测试中,你不应该使用 DI 框架。相反,只需自己实例化模拟服务并将其设置为主机对象即可。

test()
    PersonController contr = new PersonController();
    contr.personService = new TestPersonService();
    // testing contr

这被誉为DI的第一个重大成就,让像我这样不理解的人感到困惑。请参阅我的先前批评:使用applicationcontext.getbean与@configurable的优势

如果这个帖子中的DI支持者反映了DI阵营的新趋势,他们不再以那种方式进行单元测试;相反,测试也依赖于DI,具有特定于测试的DI配置。那么它与服务定位器模式没有什么区别。如果DI的主要特点是无意义的,那么它的意义何在?

您的控制器类完美地说明了这一点。它不能作为POJO在Spring DI框架之外使用。它与POJO毫无关系。而且没有人会在意,这是正确的。如果您的类依赖于服务定位器框架,情况也是一样的。

Spring beans框架提供了其他功能,其中没有一个依赖于DI;它们可以在服务定位器框架中同样实现。许多人在捍卫DI设计模式时,实际上是在捍卫整个Spring堆栈。您实际上可以将Spring用作服务定位器框架;Spring现在不会宣传这一点,因为这会打击其主要的炒作点;但是一旦炒作减弱并且必须吸引怀疑者,它就会这样做。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接