Spring @Autowired使用
在Spring中将使用@Autowired类的优点和缺点是什么?
为了澄清,我正在专门讨论@Autowired注释,而不是XML中的自动连线。
我可能只是不理解它,但对我来说,它几乎看起来像一个反模式 – 你的class级开始意识到,他们是绑定到DI框架,而不是仅仅是POJO。 也许我是一个贪婪的惩罚,但我喜欢有外部的XMLconfiguration豆,我喜欢有明确的布线,所以我知道究竟是什么有线的地方。
很长一段时间里,我相信有一个“集中式,声明式,configuration”的价值,就像我们以前使用的xml文件一样。 然后我意识到,文件中的大部分内容都不是configuration – 在开发之后从未改变过。 然后我意识到,“集中式”只有在非常小的系统中才有价值 – 只有在小型系统中,您才能够从整体上获取configuration文件。 当相同的“布线”大部分被代码中的依赖关系重复时,真正理解布线整体的价值是什么? 所以我唯一保留的是元数据(注释),它仍然是一种声明。 这些在运行时永远不会改变,他们永远不会有人会随时更改的“configuration”数据 – 所以我认为保持在代码是好的。
尽可能使用全自动布线。 我喜欢它。 除非以枪口威胁,否则我不会回到老式的spring。 我更喜欢完全@Autowired
理由随着时间而改变。
现在我认为使用自动assembly的最重要的原因是系统中有一个抽象要跟踪。 “bean名称”已经消失。 事实certificate,这个bean的名字只存在于xml中。 因此,一个完整的抽象间接层(将bean名称“foo”连接到bean“bar”中)已经消失。 现在我直接将“Foo”接口连接到我的bean中,并通过运行时configuration文件select实现。 这允许我在跟踪依赖和实现时使用代码 。 当我在我的代码中看到一个自动assembly的依赖关系时,我只需按下我的IDE中的“去实现”键,就可以得到已知实现的列表。 在大多数情况下,只有一个实现,我直接进入课堂。 不能简单得多,我总是知道到底是什么实现正在使用(我声称相反是更接近xml布线的真相 – 有趣的如何你的观点改变!)
现在你可以说这只是一个非常简单的层次,但是我们添加到系统中的每一层抽象都会增加复杂性。 我真的不认为这个xml为我所使用的任何系统添加了任何真正的价值。
我所使用的大多数系统只有一个生产运行环境的configuration。 可能还有其他的testingconfiguration等等。
我会说完整的自动assembly是spring的ruby-on-rails:它包含了大多数用例遵循的正常和常见的使用模式的概念。 使用XMLconfiguration,您可以允许许多一致性/不一致的configuration使用情况,可能/不可能是预期的。 我已经看到如此多的XMLconfiguration过度的不一致 – 它是否与代码重构? 不要想。 那些变化是有原因的吗? 通常不会。
我们在configuration中几乎不使用限定符,并find了解决这些情况的其他方法。 这是我们遇到的一个明显的“缺点”:我们稍微改变了代码的方式,使其与自动assembly平滑交互:客户存储库不再实现通用的Repository<Customer>
接口,但是我们创build了一个接口CustomerRepository
来扩展Repository<Customer>
。 有时在子类化方面还有一两招。 但是它通常只是将我们指向更强的打字方向,我发现这几乎总是一个更好的解决scheme。
但是,是的,你正在绑定一个特别的DI风格,大多是spring。 我们甚至不再为依赖项创build公共setter(所以你可能会认为我们在封装/信息隐藏部门是+1)。我们的系统中仍然有一些xml,但是xml基本上只包含exception。 完全自动assembly与xml很好地集成。
我们现在唯一需要的是@Component
, @Component
@Autowired
和其他的被包含在一个JSR(比如JSR-250 )中,所以我们不需要配合spring。 这是过去发生的事情( java.util.concurrent
东西是想到的),所以如果再次发生,我不会感到惊讶。
对我来说,这里是我喜欢/不喜欢Spring和自动布线。
优点:
- 自动布线摆脱讨厌的XMLconfiguration。
- 使用批注更容易,它允许您直接使用字段,setter方法或构造函数进行注入。 还允许您注释和“限定”注入的bean。
缺点:
- 使用自动布线和批注使您可以依赖于Spring库,与XMLconfiguration一样,您可以select使用或不使用Spring。 就像你说的,你被绑定到一个DI框架。
- 同时,我喜欢能够“符合”豆类,对我来说,这使得代码非常混乱。 如果你需要在多个地方注入相同的bean,我已经看到相同的string名称重复了。 对我来说,这似乎有可能出现错误。
我已经开始使用自动布线几乎完全在工作,因为我们非常依赖Spring集成,无论如何依赖性问题是没有意义的。 我曾经在一个广泛使用自动布线的Spring MVC项目上工作过,并且有点困难。
我认为自动布线是一个后天的习惯,一旦你习惯了,你会意识到与XMLconfiguration相比,使用它的强大,简单和更less的麻烦。
我们正在从@Autowire切换回我们大项目中的XMLconfiguration。 问题是自举性能非常低。 自动assembly扫描程序从自动assemblysearch类path加载所有类,所以在Spring初始化过程中,很多类会被急切地加载。
关于交换环境的讨论很less。 我所处理的大部分项目都是一个真正的问题,依赖于我们正在工作的环境来注入依赖项。 使用xmlconfiguration对于Spring EL来说非常简单,而且我不知道任何带注释的优秀解决scheme。 我只是想出了一个:
@Value("#{${env} == "production" ? realService : dummyService}") private SomeService service;
它应该是工作,但不是一个很好的解决scheme恕我直言。
我已经切换到@Autowire。 除了一个小项目之外,维护XMLconfiguration成为一项任务,理解力迅速下降。
IntelliJ为Spring注释提供了很好的(而不是完美的)支持。
我承认这个问题是,xmlconfiguration降低了代码的清晰度,特别是在大型系统中。
像@Component这样的注释使事情变得更糟。 它引导开发者使对象变为可变的,因为依赖关系不能作为最终的,因为需要提供缺省的构造函数。 依赖性需要通过公共setter注入,或通过@Autowired不受控制。 [甚至更糟糕的dependency injection被实例化它们的依赖关系的类所破坏,我仍然在新编写的代码中看到这一点!]。 通过不受控制,我的意思是,在大型系统中,当有多个types的实现(或子类)可用时,需要更多的参与来了解哪些实现是@Autowired,这是一个复杂的问题,使得更难调查错误。 这也意味着,假设你有一个testing环境configuration文件,另一个configuration文件是生产configuration文件,那么你的生产错误只会在最痛苦的时候发生 – 在生产中,而不是在testing环境中发现错误,甚至更好编译时间!
我坚持中间地带,我宣布我的configuration类(ES),(基于Java的Springconfiguration使用@Configuration)
我明确地在configuration类中声明了所有的bean。 我只在configuration类(es)中使用@Autowired,目的是将对Spring的依赖限制在configuration类(es)
@Configuration驻留在特定的包中,这是Spring扫描运行的唯一位置。 (这大大加快了大型项目的启动时间)
我努力使所有的类不可变,特别是数据对象,JPA,Hibernate和Spring,以及许多序列化库似乎破坏了这一点。 我避开任何迫使我提供setter的东西,或从我的财产声明中删除最后一个关键字。
减less创build对象后更改对象的可能性,大大减less了大型系统中的错误,并减less了存在时发现错误的时间。
这也似乎迫使开发人员更好地devise系统不同部分之间的交互。 问题和错误越来越多的编译错误,这减less了浪费时间,提高生产力。
这里有一些经验
优点
- 使configuration更容易,因为我们可以使用@Autowire注释
- 不想使用setter方法,所以class会更干净
缺点
- 尽pipe我们正在使用DI,但紧密地耦合到xml文件
- 很难find实施(但如果你使用像intellij好ides确定你可以摆脱这一点)
就我个人的经验而言,我并没有在testing用例中使用@AutoWire批注。
我真的很喜欢使用注释来代替XML。 根据Spring手册和最新版本,XML和Annotation取得了相同的结果。
这是我的名单
优点:
- 从XML中删除无用的行
- 简化代码的debugging:当你打开一个class级时,你可以阅读你在class上的内容
- 更快的开发,一个具有400或更多行XML的项目是可读的?
缺点:
- 不是标准的Java实现,但是您可以切换到使用@Inject,这是一个Java标准的API,所以这个bean仍然是一个Pojo
- 你不能简单地使用到处,db连接等等,但这只是一个意见,我更喜欢有一个地方阅读所有的configuration。
对于我的理解@Autowired是最好的使用,而参考接口引用和使用它的重写function,但我只发现这个问题是它有时在运行时分配给null。