问题描述
注释越来越流行。 Spring-3支持它们。 CDI依赖于他们(我不能使用没有注释的CDI,对吗?)我的问题是为什么?
我听到几个问题:
-
它有助于摆脱XML。但是xml有什么不好?依赖关系本质上是声明性的,XML对声明非常好(对命令性编程非常不利)。
有好的IDE(像想法),很容易编辑和验证xml,不是吗? -
在很多情况下,只有一个实现为每个接口。那不是真的!
我系统中几乎所有的接口都有用于测试的模拟实现。
任何其他问题?
现在我的优点对于XML:
-
您可以随时随地注入任何东西(不仅具有注释的代码)
-
如果我有一个接口的几个实现,该怎么办?使用限定词?但是它迫使我的班级知道需要什么样的注射。
这对设计来说不好。
基于XML的DI使我的代码清除:每个类都没有关于注入的想法,所以我可以配置它,并以任何方式进行单元测试。
你觉得怎么样?
我只能从Guice的经验中说出来,但这是我的看法。简而言之,基于注释的配置大大减少了您必须编写的数据,以将应用程序连接在一起,并且可以更轻松地更改取决于什么...通常甚至不必触摸配置文件本身。这样做是通过使最常见的情况绝对微不足道,而牺牲一些相对较少的情况更难处理。
我认为对于课堂不注意注入,这是一个太教条的问题。不应该在类的代码中引用注入容器。我绝对同意这一点。但是,我们必须明确一点:注释不是代码。他们自己也不会改变一个类的行为...你仍然可以创建一个具有注释的类的实例,就像它们根本不存在一样。所以你可以完全停止使用DI容器,并在那里留下注释,并且没有任何问题。
当您选择不提供类中注入的元数据提示时(即注释),您将丢弃有关该类所需的依赖关系的有价值的信息来源。你被迫在其他地方重复这个信息(以XML为例),或依靠不可靠的魔法,如自动连线,可能导致意外的问题。
要解决你的一些具体问题:
它有助于摆脱XML
许多事情对于XML配置都是不好的。
- 这是非常冗长的。
- 没有特殊工具,它不是类型安全的。 li>
- 它要求使用字符串标识符。再次,如果没有专门的工具支持,就不安全。
- 不会使用语言的特性,需要各种丑陋的结构来做一些简单的方法代码。
那就是说,我知道很多人一直在使用XML足够长的时间,以至于他们相信它只是好我不希望改变主意。
在许多情况下,每个界面只有一个实现
应用程序的单一配置的每个界面通常只有一个实现(例如生产)。关键是当启动应用程序时,通常只需要将接口绑定到单个实现。然后它可以用于许多其他组件。使用XML配置,您必须告诉使用该接口的每个组件使用该接口的一个特定绑定(如果您喜欢,则使用bean)。使用基于注释的配置,您只需声明绑定一次,并自动处理所有其他内容。这是非常重要的,并大大减少了您必须编写的配置数量。这也意味着当您向组件添加新的依赖项时,您通常不需要更改任何关于您的配置的信息!
您有模拟实现一些界面是无关紧要的。在单元测试中,通常只需创建模拟并将其传递给自己...它与配置无关。如果您使用某些界面设置了一个完整的集成测试系统,而不是改变任何东西。对于系统的集成测试运行,您仍然只使用1个实现,您只需要配置一次。
XML:可以在任何地方注入任何内容。 h2>
你可以在Guice中轻松地做到这一点,我想象你也可以在CDI中。所以这并不像你绝对阻止这样做使用基于注释的配置系统。也就是说,我冒昧地说,大多数应用程序中的大多数注入类都是类,您可以向其自己添加一个 @Inject
那里。存在用于注释的轻量级标准Java库(JSR-330)使得更多的库和框架将来更容易地为组件提供 @Inject
注释构造函数,
界面的多个实现
限定词是一个解决方案,在大多数情况下应该很好然而,在某些情况下,您确实想要做一些事情,使用特定注入类中的参数的限定符将无法正常工作...通常是因为您希望有多个 类型的实例,每个实例使用一个不同的界面实现或实例。 Guice用一个叫 PrivateModule
的东西来解决这个问题。我不知道CDI在这方面提供什么。但是,再一次,这是一个少数的情况,只要你能处理它,它不值得让您的配置的其余部分受到损害。
Annotations becoming popular. Spring-3 supports them. CDI depends on them heavily (I can not use CDI with out of annotations, right?)
My question is why?
I heard several issues:
"It helps get rid of XML". But what is bad about xml? Dependencies are declarative by nature, and XML is very good for declarations (and very bad for imperative programming).With good IDE (like idea) it is very easy to edit and validate xml, is not it?
"In many cases there is only one implementation for each interface". That is not true!Almost all interfaces in my system has mock implementation for tests.
Any other issues?
And now my pluses for XML:
You can inject anything anywhere (not only code that has annotations)
What should I do if I have several implementations of one interface? Use qualifiers? But it forces my class to know what kind of injection it needs.It is not good for design.
XML based DI makes my code clear: each class has no idea about injection, so I can configure it and unit-test it in any way.
What do you think?
I can only speak from experience with Guice, but here's my take. The short of it is that annotation-based configuration greatly reduces the amount you have to write to wire an application together and makes it easier to change what depends on what... often without even having to touch the configuration files themselves. It does this by making the most common cases absolutely trivial at the expense of making certain relatively rare cases slightly more difficult to handle.
I think it's a problem to be too dogmatic about having classes have "no idea about injection". There should be no reference to the injection container in the code of a class. I absolutely agree with that. However, we must be clear on one point: annotations are not code. By themselves, they change nothing about how a class behaves... you can still create an instance of a class with annotations as if they were not there at all. So you can stop using a DI container completely and leave the annotations there and there will be no problem whatsoever.
When you choose not to provide metadata hints about injection within a class (i.e. annotations), you are throwing away a valuable source of information on what dependencies that class requires. You are forced to either repeat that information elsewhere (in XML, say) or to rely on unreliable magic like autowiring which can lead to unexpected issues.
To address some of your specific questions:
It helps get rid of XML
Many things are bad about XML configuration.
- It's terribly verbose.
- It isn't type-safe without special tools.
- It mandates the use of string identifiers. Again, not safe without special tool support.
- Doesn't take any advantage of the features of the language, requiring all kinds of ugly constructs to do what could be done with a simple method in code.
That said, I know a lot of people have been using XML for long enough that they are convinced that it is just fine and I don't really expect to change their minds.
In many cases there is only one implementation for each interface
There is often only one implementation of each interface for a single configuration of an application (e.g. production). The point is that when starting up your application, you typically only need to bind an interface to a single implementation. It may then be used in many other components. With XML configuration, you have to tell every component that uses that interface to use this one particular binding of that interface (or "bean" if you like). With annotation-based configuration, you just declare the binding once and everything else is taken care of automatically. This is very significant, and dramatically reduces the amount of configuration you have to write. It also means that when you add a new dependency to a component, you often don't have to change anything about your configuration at all!
That you have mock implementations of some interface is irrelevant. In unit tests you typically just create the mock and pass it in yourself... it's unrelated to configuration. If you set up a full system for integration tests with certain interfaces using mocks instead... that doesn't change anything. For the integration test run of the system, you're still only using 1 implementation and you only have to configure that once.
XML: You can inject anything anywhere
You can do this easily in Guice and I imagine you can in CDI too. So it's not like you're absolutely prevented from doing this by using an annotation-based configuration system. That said, I'd venture to say that the majority of injected classes in the majority of applications are classes that you can add an @Inject
to yourself if it isn't already there. The existence of a lightweight standard Java library for annotations (JSR-330) makes it even easier for more libraries and frameworks to provide components with an @Inject
annotated constructor in the future, too.
More than one implementation of an interface
Qualifiers are one solution to this, and in most cases should be just fine. However, in some cases you do want to do something where using a qualifier on a parameter in a particular injected class would not work... often because you want to have multiple instances of that class, each using a different interface implementation or instance. Guice solves this with something called PrivateModule
s. I don't know what CDI offers in this regard. But again, this is a case that is in the minority and it's not worth making the rest of your configuration suffer for it as long as you can handle it.
这篇关于Java依赖注入:XML或注释的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!