Spring @Autowired用法


218

在Spring会连接的类中使用@Autowired的优缺点是什么?

只是为了澄清一下,我是在专门讨论@Autowired注释,而不是XML的自动装配

我可能只是不了解它,但是对我来说,这几乎像是一种反模式-您的类开始意识到它们与DI框架相关联,而不仅仅是POJO。也许我是一个受惩罚的but嘴,但我喜欢为bean使用外部XML配置,并且我喜欢进行显式的布线,因此我确切知道在哪里布线。


4
我也对这个主题感兴趣-通过注释而不是XML配置MVC应用程序似乎会导致大量搜索“哪个类映射到此URL?”。“谁在处理这个?”。我希望有一个单一的配置来源
matt b

6
“ @Autowiring”一词在这里似乎具有误导性。由于您还可以使用XML配置进行自动装配,因此原始问题应改为“使用Spring注释的利弊”。提供的答案更多地侧重于自动装配方面,而较少侧重于使用注释方面。
Neeme Praks 09年

Answers:


253

很长时间以来,我相信拥有像我们所有人过去使用的xml文件一样的“集中式,声明式配置”是有价值的。然后我意识到文件中的大多数内容不是配置文件-开发后从未在任何地方进行过更改。然后我意识到,“集中”只有在非常小的系统价值-只有在小型系统会你永远能够神交配置文件作为一个整体。当相同的“接线”主要由代码中的依赖项复制时,从整体上理解接线的真正价值是什么?因此,我唯一保留的是元数据(注释),它仍然是声明性的。这些永远不会在运行时更改,也永远不会 有人会即时更改的“配置”数据-所以我认为将其保存在代码中很好。

我会尽量使用全自动布线。我喜欢它。除非有枪口威胁,否则我不会回到老式的春天。@Autowired随着时间的流逝,我完全喜欢的理由已经改变。

现在,我认为使用自动装配的最重要原因是系统中要跟踪的抽象较少。“ bean名称”实际上已经消失了。事实证明,由于xml,bean名称仅存在。因此,完整的抽象间接层(将bean名称“ foo”连接到bean“ bar”的地方)消失了。现在,我将“ Foo”接口直接连接到我的bean中,并通过运行时配置文件选择实现。这使我可以在跟踪依赖关系和实现时使用代码。当我在代码中看到自动装配的依赖项时,只需在IDE中按“转到实现”键,就会出现已知实现的列表。在大多数情况下,只有一个实现,而我直接进入课堂。能够' 正在使用什么实现(我声称与xml连线相反的事实更接近真相-有趣的是您的视角如何改变!)

现在您可以说这只是一个非常简单的层,但是我们添加到系统中的每个抽象层都会增加复杂性。我真的不认为xml可以为我使用过的任何系统增加任何实际价值。

我曾经使用过的大多数系统只有一个生产运行时环境的配置。可能还有其他测试配置等等。

我要说的是,完全自动装配是Spring的“红宝石”:它包含这样一种观念,即大多数用例都遵循一种正常且通用的使用模式。使用XML配置,您可以允许 /可能不希望使用大量一致/不一致的配置。我已经看到太多的xml配置因不一致而变得过分-它是否与代码一起重构?以为没有。这些变化是有原因的吗?通常不会。

我们几乎没有在配置中使用限定符,而是找到了解决这些情况的其他方法。这是我们遇到的一个明显的“缺点”:我们已经稍微改变了编码方式,使其与自动装配的交互更加流畅:客户存储库不再实现通用Repository<Customer>接口,而是使接口CustomerRepository可扩展Repository<Customer>。有时在子类化方面还有一两个窍门。但这通常只是为我们指明了更强类型的方向,我发现这几乎总是一个更好的解决方案。

但是,是的,您绑定的是大多数spring都采用的特定DI风格。我们甚至不再为依赖项设置公共设置器(因此,您可以说我们在封装/信息隐藏部门中为+1)。我们的系统中仍然有一些xml,但是xml基本上包含异常。完全自动装配与xml很好地集成在一起。

现在,我们唯一需要的就是将@Component@Autowired其余的都包含在JSR中(例如JSR-250),因此我们不必与spring捆绑在一起。这就是过去发生的事情的方式(这些java.util.concurrent东西浮现在脑海中),所以如果再次发生这种情况,我不会感到完全惊讶。


5
Spring支持javax.annotation / javax.inject,因此您不必对Spring具有代码依赖性。
Michael Wiles 2012年

26

对我来说,这是我喜欢/不喜欢Spring和自动装配的东西。

优点:

  • 自动装配摆脱了讨厌的XML配置。
  • 使用注释要容易得多,它使您可以直接使用字段,setter方法或构造函数进行注入。还允许您注释和“限定”注入的bean。

缺点:

  • 使用自动装配和注释使您依赖于Spring库,在XML库中,可以选择在有无Spring的情况下运行。就像您说的那样,您将与DI框架绑定在一起。
  • 同时,我喜欢能够“限定” bean,这对我来说使代码非常混乱。如果您需要在多个位置注入相同的bean,我已经看到了相同的字符串名称。在我看来,这似乎有可能出错。

我几乎在工作中就开始使用自动装配,因为无论如何我们都非常依赖于Spring集成,因此依赖问题尚无定论。我参与了一个Spring MVC项目,该项目广泛使用自动装配,很难缠住我的头。

我认为自动装配是一种后天的品味,一旦习惯了它,您就会意识到与XML配置相比,使用它的功能多么强大,容易并且没有太多麻烦。


3
如果您使用免费的Springsource Tool Suite,它具有自动完成功能,bean图等功能,那么xml配置的麻烦就少了
Sean Patrick Floyd 2010年

我完全同意自动布线变得凌乱并且依赖于弹簧库!我从未使用过XML配置,并且在考虑是否应该走这条路?
James111 '16

15

在我们的大型项目中,我们将从@Autowire切换回XML配置。问题是引导程序性能很低。自动装配扫描程序从自动装配搜索类路径加载所有类,因此,在Spring初始化期间急切地加载了许多类。


1
我发现javaconfig甚至可能是启动部分上下文的更好的解决方案,这是一个很大的胜利,但是您可以通过在构造函数上使用@ Autowired / @ Inject来轻松组合它们(换句话说,切换到构造函数注入)。
krosenvold

6

关于交换环境的讨论很少。我从事的大多数项目都是一个实际的问题,取决于我们正在研究的环境来注入依赖项。使用xml config,使用Spring EL非常简单,而且我不知道任何带有注释的不错的解决方案。我刚想出一个:

    @Value("#{${env} == "production" ? realService : dummyService}")
    private SomeService service;

它应该可以工作,但是不是一个不错的解决方案。


打开我这个一个单独的线程,并有和春天有个解决办法@Profiles@Configurationblog.springsource.org/2011/02/14/... 又见其他线程:stackoverflow.com/questions/13490393/...
BTakacs

4

我已经切换到@Autowire。维护除小型项目以外的任何其他项目上的XML配置本身就是一项任务,并且理解能力迅速下降。

IntelliJ为Spring注释提供了很好的(不是完美的)支持。


3

我对此主题的看法是,xml配置降低了代码的清晰度,尤其是在大型系统中。

像@Component这样的注释会使情况更糟。它引导开发人员使对象可变,因为鉴于需要提供默认的构造函数,因此无法再使依赖关系最终化。依赖关系需要通过公共设置器注入,或者通过@Autowired不受控制。[甚至更差的依赖注入都被实例化其依赖的类所破坏,我仍然在新编写的代码中看到这一点!]。不受控制,我的意思是,在大型系统中,当类型的多个实现(或子代)可用时,要弄清楚哪些实现是@Autowired会涉及更多的工作,这种复杂性使调查错误变得更加困难。这也意味着,假设您有一个用于测试环境的配置文件,另一个用于生产环境的配置文件,

我坚持在中间声明我的配置类,(使用@Configuration的基于Java的Spring配置)

我在配置类中明确声明了所有bean。我只在配置类中使用@Autowired,目的是将对Spring的依赖性限制为配置类

@Configuration驻留在特定的程序包中,这是运行春季扫描的唯一位置。(这大大加快了大型项目的启动时间)

我努力使所有类不变,尤其是数据对象,JPA,Hibernate和Spring,以及许多序列化库似乎破坏了这一点。我避免使用任何强迫我提供设置器的方法,或者从属性声明中删除final关键字。

减少了创建对象后更改对象的可能性,从而大大减少了大型系统中的错误,并减少了存在时发现错误的时间。

似乎也迫使开发人员更好地设计系统不同部分之间的交互。问题和错误变成越来越多的编译错误,从而减少了浪费的时间并提高了生产率。


1

这是一些经验
专家

  • 因为我们可以只使用@Autowire批注,所以使配置更容易
  • 不想使用setter方法,因此类会更干净

缺点

  • 即使我们正在使用DI,也紧密耦合到xml文件
  • 很难找到实现(但是,如果您使用了像intellij这样的好主意,那么您可以摆脱这一点)

从我的个人经验来看,我没有使用@AutoWire注释,而是在测试案例中使用了很多。


1

我真的很喜欢用注释而不是XML编写。根据Spring手册和最新版本,XML和Annotation获得了相同的结果。

这是我的清单

优点:

  • 从xml删除无用的行
  • 简化代码调试:打开课程时,您可以阅读课程中的内容
  • 开发速度更快,具有400行或更多行XML的项目可读吗?

缺点:

  • 不是标准的Java实现,但是您可以切换为使用@Inject,这是Java标准的Api,因此bean仍然是Pojo
  • 您不能简单地在任何地方使用数据库连接等等,但这只是一个见解,我希望有一个可以读取所有配置的地方。

0

就我的理解而言,@ Autowired是在引用接口引用并使用其覆盖功能时最好的用法,但是我唯一发现的问题是它有时会在运行时分配为null。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.