Spring @Autowired 用法

发布于 07-14 15:37 字数 271 浏览 9 评论 0原文

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

澄清一下,我具体讨论的是 @Autowired 注释,而不是 XML 中的自动装配。

我可能只是不明白它,但对我来说,这几乎像是一种反模式 - 你的类开始意识到它们与 DI 框架相关,而不仅仅是 POJO。 也许我是一个贪图惩罚的人,但我喜欢为 bean 提供外部 XML 配置,并且我喜欢有明确的连接,所以我确切地知道什么连接在哪里。

What are the pros and cons of using @Autowired in a class that will be wired up by Spring?

Just to clarify, I'm talking specifically about the @Autowired annotation, not auto-wiring in XML.

I probably just don't understand it, but to me it almost seems like an anti-pattern - your classes start to become aware that they are tied to a DI framework, rather than just being POJOs. Maybe I'm a glutton for punishment, but I like having the external XML config for beans, and I like to have explicit wirings, so I know exactly what is wired where.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(9

浮光之海2024-07-21 15:37:55

很长一段时间以来,我相信拥有“集中式、声明性、配置”(就像我们过去都使用的 xml 文件)是有价值的。 然后我意识到文件中的大部分内容都不是配置 - 它在开发后从未在任何地方发生过更改。 然后我意识到“集中式”仅在相当小的系统中才有价值 - 只有在小型系统中,您才能够理解配置文件作为一个整体。 当相同的“接线”大部分由代码中的依赖项重复时,理解整个接线的真正价值是什么? 所以我唯一保留的是元数据(注释),它仍然是一种声明性的。 这些永远在运行时改变,并且它们永远是某人会即时更改的“配置”数据 - 所以我认为将其保留在代码中是很好的。

我尽可能使用全自动接线。 我喜欢它。 除非受到枪口威胁,否则我不会回到旧式春天。 随着时间的推移,我完全喜欢 @Autowired 的原因已经发生了变化。

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

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

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

我想说,完全自动装配是 spring 的 ruby​​-on-rails:它包含这样的概念:大多数用例都遵循正常且常见的使用模式。 使用 XML 配置,您允许大量可能/可能不是预期的一致/不一致的配置使用。 我见过很多 xml 配置过度不一致 - 它是否与代码一起重构? 没想到。 这些变化是有原因的吗? 通常不会。

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

但是,是的,您正在与一种特定的 DI 风格联系在一起,而这种风格主要是 spring 所做的。 我们甚至不再为依赖项创建公共设置器(所以你可能会说我们在封装/信息隐藏部门+1)我们的系统中仍然有一些 xml,但 xml 基本上仅 包含异常。 完全自动装配与 xml 完美集成。

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

For a long time I believed that there was a value in having a "centralized, declarative, configuration" like the xml files we all used to use. Then I realized that most of the stuff in the files wasn't configuration - it was never changed anywhere after development, ever. Then I realized that "centralized" only has value in quite small systems - only in small systems will you ever be able to grok a configuration file as a whole. And what is really the value of understanding the wiring as a whole, when the same "wirings" are mostly duplicated by dependencies in the code? So the only thing I've kept is meta-data (annotations), which is still kind-of declarative. These never change at runtime and they're never "configuration" data that someone will change on the fly - so I think keeping it in the code is nice.

I use full auto-wiring as much as I can. I love it. I won't go back to old-style spring unless threatened at gun-point. My reasons for preferring fully @Autowired have changed over time.

Right now I think the most important reason for using autowiring is that there's one less abstraction in your system to keep track of. The "bean name" is effectively gone. It turns out the bean name only exists because of xml. So a full layer of abstract indirections (where you would wire bean-name "foo" into bean "bar") is gone. Now I wire the "Foo" interface into my bean directly, and implementation is chosen by run-time profile. This allows me to work with code when tracing dependencies and implementations. When I see an autowired dependency in my code I can just press the "go to implementation" key in my IDE and up comes the list of known implementations. In most cases there's just one implementation and I'm straight into the class. Can't be much simpler than that, and I always know exactly what implementation is being used (I claim that the opposite is closer to the truth with xml wiring - funny how your perspective changes!)

Now you could say that it's just a very simple layer, but each layer of abstraction that we add to our systems increase complexity. I really don't think the xml ever added any real value to any system I've worked with.

Most systems I've ever work with only have one configuration of the production runtime environment. There may be other configurations for test and so on.

I'd say that full autowiring is the ruby-on-rails of spring: It embraces the notion that there's a normal and common usage pattern that most use cases follow. With XML configuration you permit a lot of consistent/inconsistent configuration usage that may/may not be intended. I've seen so much xml configuration go overboard with inconsistencies - does it get refactored together with the code ? Thought not. Are those variations there for a reason? Usually not.

We hardly use qualifiers in our configuration, and found other ways to solve these situations. This is a clear "disadvantage" we encounter: We've slightly changed the way we code to make it interact smoother with autowiring: A customer repository no longer implements the generic Repository<Customer> interface but we make an interface CustomerRepository that extends Repository<Customer>. Sometimes there's also a trick or two when it comes to subclassing. But it usually just points us in the direction of stronger typing, which I find is almost always a better solution.

But yes, you're tying to a particular style of DI that mostly spring does. We don't even make public setters for dependencies any more (So you could argue that we're +1 in the encapsulation/information hiding department) We still have some xml in our system, but the xml basically only contains the anomalies. Full autowiring integrates nicely with xml.

The only thing we need now is for the @Component, @Autowired and the rest to be included in a JSR (like JSR-250), so we don't have to tie in with spring. This is the way things have been happening in the past (the java.util.concurrent stuff springs to mind), so I wouldn't be entirely surprised if this happened again.

丘比特射中我2024-07-21 15:37:55

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

优点:

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

缺点:

  • 使用自动装配和注释会使您依赖于 Spring 库,而使用 XML 配置时您可以选择使用或不使用 Spring 来运行。 正如您所说,您会与 DI 框架联系在一起。
  • 同时我喜欢能够“限定”bean,对我来说这使得代码非常混乱。 如果您需要在多个位置注入相同的 bean,我已经看到相同的字符串名称到处重复。 对我来说,这似乎有可能出错。

我开始在工作中几乎完全使用自动装配,因为无论如何我们都非常依赖 Spring 集成,以至于依赖问题没有实际意义。 我参与了一个 Spring MVC 项目,该项目广泛使用了自动装配,但有点难以理解。

我认为自动装配是一种后天习得的习惯,一旦你习惯了它,你就会意识到它是多么强大、简单,而且比 XML 配置更容易使用。

For me here is what I like/dislike about Spring and auto-wiring.

Pros:

  • Auto-wiring gets rid of nasty XML configuration.
  • Much easier to use annotations which allows you to inject directly using fields, setter methods, or constructors. Also allows you to annotate and 'qualify' your injected beans.

Cons:

  • Using auto-wiring and annotations makes you dependent on Spring libraries where as with XML configuration you could chose to run with or without Spring. Like you said, you become tied to a DI framework.
  • At the same time I like being able to 'qualify' beans, to me this makes the code really messy. If you need to inject the same bean in multiple places, I've seen the same string name repeated all over. To me this seems to have the potential for errors.

I've started using auto-wiring almost exclusively at work because we depend so much on Spring integration anyway that the dependency issue is moot. I worked on a Spring MVC project that used auto-wiring extensively and was a little hard to wrap my head around.

I think auto-wiring is an acquired taste, once you get used to it you realize how powerful, easy, and much less of a headache it is to work with than the XML configuration.

冷弦2024-07-21 15:37:55

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

We are switching from @Autowire back to XML configuration in our big project. The problem is very low bootstrap performance. Autowiring scanner loads all classes from autowiring search classpath, so, lots of classes are loaded eagerly during Spring initialization.

冷默言语2024-07-21 15:37:55

关于切换环境的讨论很少。 我参与过的大多数项目都是根据我们正在处理的环境注入依赖项的真正问题。 使用 xml 配置,Spring EL 非常简单,而且我不知道有任何好的注释解决方案。 我刚刚想出了一个:

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

它应该有效,但恕我直言,这不是一个很好的解决方案。

There has been very little discussion about switching environments. Most projects I've worked on it was a real issue to inject dependencies depending on the environment we are working on. With xml config it's pretty straightforward with Spring EL, and I am not aware of any nice solution with annotations. I've just figured out one:

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

It should be working, but not a nice solution imho.

兔小萌2024-07-21 15:37:55

我已经切换到@Autowire。 除了小项目之外,维护 XML 配置本身就是一项任务,并且理解力很快就会下降。

IntelliJ 为 Spring 注解提供了良好(但不是完美)的支持。

I have switched to @Autowire. Maintaining the XML configuration on anything other than a small project became a task in it's own right and comprehension quickly degraded.

IntelliJ provides good (not perfect) support for Spring annotations.

鯉魚旗2024-07-21 15:37:55

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

像 @Component 这样的注释会让事情变得更糟。 它引导开发人员使对象可变,因为考虑到需要提供默认构造函数,依赖项不能再成为最终的。 依赖关系需要通过公共 setter 注入,或者通过 @Autowired 不受控制。 [更糟糕的是,依赖注入会受到实例化其依赖项的类的影响,我仍然在新编写的代码中看到这一点!]。 我所说的不受控制是指,在大型系统中,当该类型的多个实现(或子级)可用时,需要更多地了解哪些实现是@Autowired,这种复杂性使得调查错误变得更加困难。 这也意味着,假设您有一个用于测试环境的配置文件和另一个用于生产环境的配置文件,那么您的生产错误只会在最严重的情况下发生 - 在生产中,而不是能够在测试环境中发现错误,甚至更好的是在编译时间!

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

我在配置类中显式声明我的所有bean。 我只在配置类中使用@Autowired,目的是限制Spring对配置类的依赖。

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

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

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

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

My take on this subject is that, xml configuration reduce the clarity of the code, especially in large systems.

Annotations like @Component makes things even worse. It steers developers to make objects mutable, as dependencies can't be made final anymore, given that default constructors need to be provided. Dependencies need to be either injected through public setter, or uncontrolled through @Autowired. [even worse dependency injection is compromised with classes that instantiate their dependencies, I still see this in newly written code!]. By uncontrolled I mean, in large systems, when multiple implementations (or children) of the type are available, it gets much more involved to understand which of the implementations was @Autowired, a complexity that makes investigating bugs much harder. It also means that, supposedly you have a profile for test environment and another for production, your production bugs will only happen when it hurts most - in production, rather than being able to spot the bugs in the test environment, or even better, at compile time!

I stick to the middle ground where I declare my configuration class(es), (java based Spring configuration using @Configuration)

I declare all my beans explicitly in the configuration class(es). I only use @Autowired in the configuration class(es), the purpose is to limit dependency on Spring to the configuration class(es)

The @Configuration reside in a specific package, that's the only place where the spring scan runs. (That speeds up start time substantially in large projects)

I strive to make all my classes immutable, especially the data object, JPA, Hibernate and Spring, as well as many serialization libraries seem to undermine this. I steer away from anything that forces me to provide setters, or remove the final keyword from my property declaration.

Reducing the possibilities of changing objects after they're created, reduces substantially the bugs in large system as well as reduces the time to find a bug when one exists.

It also seems that it forces developer to better design the interaction between the different parts of the system. Problems and bugs become more and more compilation errors, that reduces wasted time and improve productivity.

月光色2024-07-21 15:37:55

以下是一些经验
优点

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

缺点

  • 与 xml 紧密耦合文件,即使我们使用 DI
  • 很难找到实现(但如果你使用像 intellij 这样的好IDE,你肯定可以摆脱这个)

根据我的个人经验,我没有太多使用 @AutoWire 注释,但在测试用例中。

Here are some of experience
Pros

  • Makes easier to configure because we can just use @Autowire annotation
  • Don't want to use setter methods , so class will be more clean

Cons

  • Tightly couple to xml file even though we are using DI
  • Hard to find implementation (But if you your using good ides like intellij sure you can get rid of this)

As of my personal experiences I didn't use @AutoWire annotation that much but in test cases.

等风来2024-07-21 15:37:55

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

这是我的清单

优点:

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

缺点:

  • 不是标准的Java实现,但是你可以切换到使用@Inject,它是一个Java标准Api,所以bean仍然是一个Pojo
  • 你不能简单地在任何地方使用,数据库连接e等等,但这只是一个意见,我更喜欢有一个地方可以读取所有配置。

I really love write with annotations, instead of XML.
According to the Spring manual and the last versions, XML and Annotation achieved the same result.

This is my list

Pro:

  • Remove useless line from xml
  • Simplify the debugging the code: when you open a class, you can read what you have in the class
  • More fast developping, a project with 400 or more line of XML is readable?

Cons:

  • Is not standard Java implementation, but you can switch to use @Inject, which is a Java Standard Api, so the bean remain a Pojo
  • You cannot simply use everywhere, db connection e so on, but it's only an opinion, i prefer have a place where read all configuration.
苦行僧2024-07-21 15:37:55

据我了解,@Autowired 是在引用接口引用并使用其覆盖函数时最好使用的,但我唯一发现的问题是它有时在运行时分配为 null。

For my understanding @Autowired is the best to use while refer to interface reference and use its override funtions, but I only find issue with this is that it sometimes assigned to null at runtime.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文