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

为了澄清一下,我特别讨论的是@Autowired注释,而不是XML中的自动连接。

我可能只是不理解它,但对我来说,这似乎是一种反模式——您的类开始意识到它们被绑定到DI框架上,而不仅仅是pojo。也许我是一个贪吃惩罚的人,但是我喜欢为bean使用外部XML配置,而且我喜欢显式连接,这样我就确切地知道在哪里连接了什么。


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

优点:

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

缺点:

使用自动连接和注释使您依赖于Spring库,与XML配置一样,您可以选择使用或不使用Spring运行。如您所说,您将绑定到DI框架。 与此同时,我喜欢能够“限定”bean,对我来说,这使代码非常混乱。如果您需要在多个地方注入相同的bean,我看到过在各处重复使用相同的字符串名称。在我看来,这似乎有潜在的错误。

我已经开始几乎只在工作中使用自动连接,因为我们太依赖Spring集成了,所以依赖关系问题是没有意义的。我曾经在一个Spring MVC项目中工作过,这个项目大量使用了自动连接,有点难以理解。

我认为自动连接是一种后天养成的习惯,一旦习惯了它,您就会意识到它是多么强大、简单,而且使用起来比使用XML配置少得多。


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.

我尽可能多地使用全自动布线。我很喜欢。除非有人用枪威胁我,否则我不会回到老式的春天。随着时间的推移,我完全喜欢@Autowired的原因已经改变了。

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!)

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

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

我想说,完全自动装配是弹簧上的红宝石:它包含了大多数用例遵循的正常和常见的使用模式的概念。使用XML配置,您允许使用许多可能/可能不希望使用的一致/不一致配置。我见过太多xml配置的不一致——它会和代码一起重构吗?认为不是。这些变化是有原因的吗?通常不会。

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.

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

现在我们唯一需要做的就是将@Component、@Autowired和其他组件包含在JSR(如JSR-250)中,这样我们就不必与spring绑定。这是过去发生的事情的方式(想到java.util.concurrent的东西),所以如果再次发生这种情况,我不会完全感到惊讶。


我已经切换到@Autowire。在小型项目以外的任何项目上维护XML配置都成为了一项独立的任务,而且理解能力很快就下降了。

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


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


我对这个主题的看法是,xml配置降低了代码的清晰度,特别是在大型系统中。

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!

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

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

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

我努力使我的所有类都是不可变的,尤其是数据对象、JPA、Hibernate和Spring,以及许多序列化库似乎都破坏了这一点。我避免任何强迫我提供setter或从属性声明中删除最后一个关键字的操作。

减少对象创建后更改的可能性,大大减少了大型系统中的bug,并减少了在存在bug时查找bug的时间。

它似乎还迫使开发人员更好地设计系统不同部分之间的交互。问题和bug变成越来越多的编译错误,这减少了浪费的时间,提高了工作效率。


以下是一些经验 优点

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

Cons

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

就我个人经验而言,除了在测试用例中,我很少使用@AutoWire注释。


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

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

它应该会起作用,但不是一个很好的解决方案。


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

这是我的清单

Pro:

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

缺点:

不是标准的Java实现,但您可以切换到使用@Inject,这是一个Java标准Api,因此bean仍然是Pojo 你不能简单地到处使用,db连接等等,但这只是一个观点,我更喜欢有一个地方读取所有配置。


根据我的理解,@Autowired是最好的使用,同时参考接口引用和使用它的覆盖函数,但我只发现问题是,它有时在运行时被分配为null。