java 依赖注入和 Spring 框架是关于什么的?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1980182/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
What are Dependency Injection & Spring Framework about?
提问by EugeneP
Possible Duplicates:
What is dependency injection?
What exactly is Spring for?
可能的重复:
什么是依赖注入?
Spring究竟是干什么用的?
I want to know What is Spring Framework? Why and when should one use it in Java Enterprise development? The answer would be "A dependency injection framework". All right, what advantages do we have when using dependency injection frameworks? The idea of describing classes with setter values and/or constructor parameters seems strange to me. Why do that? Because we can change the properties without recompiling the project? Is that all that we gain?
我想知道什么是Spring框架?为什么以及何时应该在 Java Enterprise 开发中使用它? 答案是“依赖注入框架”。好了,我们使用依赖注入框架有什么优势呢?用 setter 值和/或构造函数参数描述类的想法对我来说似乎很奇怪。为什么要这样做?因为我们可以在不重新编译项目的情况下更改属性?这就是我们获得的全部吗?
Then, what objects should we describe in beans.xml? All objects or only a few?
那么,我们应该用哪些对象来描述beans.xml呢?所有对象还是只有几个?
The simplest answers are welcome
欢迎最简单的答案
回答by Mark Seemann
We use Dependency Injection (DI) to implement loose coupling. The choice of any particulary DI Container is not that important.
我们使用依赖注入(DI)来实现松耦合。任何特定 DI 容器的选择都不是那么重要。
Every time you create an instance of a class by using the newkeyword, you tightly couple your code to that class, and you will not be able to substitute that particularl implementation with a different one (at least not without recompiling the code).
每次使用new关键字创建类的实例时,都会将代码与该类紧密耦合,并且无法用不同的实现替换该特定实现(至少在不重新编译代码的情况下不能)。
This would look something like this in C# (but would be equivalent in Java):
这在 C# 中看起来像这样(但在 Java 中是等价的):
public class MyClass
{
public string GetMessage(int key)
{
return new MessageService().GetMessage(key)
}
}
This means that if you would later like to use a different MessageService, you can't.
这意味着,如果您以后想使用不同的 MessageService,则不能。
On the other hand, if you inject an interface into the class and adhere to the Liskov Substition Principle, you will be able to vary the consumer and the service independently.
另一方面,如果您将接口注入类并遵守Liskov 替换原则,您将能够独立地改变消费者和服务。
public class MyClass
{
private readonly IMessageService messageService;
public MyClass(IMessageService messageService)
{
if(messageService == null)
{
throw new ArgumentNullException("messageService");
}
this.messageService = messageService;
}
public string GetMessage(int key)
{
return this.messageService.GetMessage(key)
}
}
Although this looks more complicated, we have now managed to follow the Single Responsibility Principleby ensuring that each collaborator does only one thing, and that we can vary both independently of each other.
虽然这看起来更复杂,但我们现在已经设法遵循单一职责原则,确保每个合作者只做一件事,并且我们可以彼此独立地改变两者。
Furthermore, we can now change MyClass' behavior without changing the class itself, thus adhering to the Open/Closed Principle.
此外,我们现在可以在不改变类本身的情况下改变 MyClass 的行为,从而遵守开放/封闭原则。
回答by Pablo Fernandez
Reconfiguration is overrated. The most important thing you get from using DI is testability. Since your classes don't depend on implementations but on abstractions you can replace them with mocks / stubs in your unit tests.
重新配置被高估了。您从使用 DI 中获得的最重要的东西是可测试性。由于您的类不依赖于实现而是依赖于抽象,因此您可以在单元测试中用模拟/存根替换它们。
Example
例子
Without DI:
没有 DI:
class SaleAction{
private BillingService billingService;
public SaleAction(){
billingService = new CreditCardService(); //dependency is hardcoded
}
public void pay(long amount){
//pre payment logic
billingService.pay(amount);
//post payment logic
}
}
In that example suppose you want to unit test the pre-payment logic and post-payment logic of SaleAction... you can't because SaleActionis coupled to CreditCardServiceand probably running your tests will generate fake payments.
在该示例中,假设您想对...的预付款逻辑和后付款逻辑进行单元测试,SaleAction因为SaleAction它与CreditCardService您的测试相耦合并且运行您的测试可能会生成假付款。
Now the same example with DI:
现在与 DI 相同的示例:
class SaleAction{
private BillingService billingService;
public SaleAction(BillingService service){
billingService = service; //DI
}
public void pay(long amount){
//pre payment logic
billingService.pay(amount);
//post payment logic
}
}
Now SaleActionis decoupled from any implementation, which means that in your test you can do SaleAction action = new SaleAction(new DummyBillingService());.
NowSaleAction与任何实现分离,这意味着在您的测试中您可以执行SaleAction action = new SaleAction(new DummyBillingService());.
Hope that helps, there's also thearticle about DI, written by Martin Fowler that you can find here
希望有所帮助,您还可以在此处找到 Martin Fowler 撰写的有关 DI的文章
回答by Bozho
Here's a good articleexplaining the ideas of spring. (By Rod Johnson, the founder of the Spring framework)
这是一篇很好的文章,解释了 spring 的想法。(作者 Rod Johnson,Spring 框架的创始人)
回答by Ken Fox
Spring has turned into a huge framework, which may be confusing you if you are only trying to wrap your head around dependency injection. The Google Guice project is tiny and only does DI with pure Java--no XML and no extras. There's a nice introductory video explaining DI too. http://code.google.com/p/google-guice/
Spring 已经变成了一个巨大的框架,如果您只是试图围绕依赖注入,这可能会让您感到困惑。Google Guice 项目很小,只使用纯 Java 进行 DI —— 没有 XML,也没有额外的东西。还有一个很好的介绍性视频,解释了 DI。http://code.google.com/p/google-guice/
回答by duffymo
I think I can take a crack at the question, although I'm not sure that any answer will be satisfactory.
我想我可以解决这个问题,尽管我不确定任何答案都会令人满意。
The easy answer is that Spring is combination of technologies:
简单的答案是 Spring 是技术的组合:
- dependency injection, which uses the Hollywood principle to help you keep interface and implementation separate;
- aspect oriented programming, which isolates cross cutting concerns into modules that you can apply declaratively. The "hello world" of AOP is logging, but it's all over Spring (e.g. transactions, dynamic proxies for remoting, security, etc.) Think servlet filters and you'll have the idea;
- libraries to help with common tasks like persistence (JDBC, Hibernate, iBatis, JDO, JPA, etc.), remoting (RMI, HTTP, web services), asynch messaging (message driven POJOs), validating and binding, web MVC (Spring or Struts), utilities like e-mail, scheduling, security, etc.
- 依赖注入,它使用好莱坞原则来帮助您将接口和实现分开;
- 面向方面的编程,它将横切关注点隔离到您可以声明式应用的模块中。AOP 的“hello world”是日志记录,但它遍布 Spring(例如事务、远程处理的动态代理、安全性等)。想想 servlet 过滤器,你就会有想法;
- 帮助处理常见任务的库,如持久性(JDBC、Hibernate、iBatis、JDO、JPA 等)、远程处理(RMI、HTTP、Web 服务)、异步消息传递(消息驱动的 POJO)、验证和绑定、Web MVC(Spring 或Struts)、电子邮件、日程安排、安全等实用程序。
But the deeper answer is that you're getting the benefit of Rod Johnson's experience as a consultant on Java EE projects. He distilled what worked for him on his gigs into Interface 21/Spring, and now you can have the benefit of all that for free.
但更深层次的答案是,您正在从 Rod Johnson 作为 Java EE 项目顾问的经验中获益。他将在他的演出中对他有用的东西提炼到 Interface 21/Spring 中,现在您可以免费获得所有这些好处。
The Spring team writes code that is designed, tested, and follows standards more rigorously than anything I'll ever write. (Imagine Juergen Hoeller browbeating Rod Johnson because his code didn't meet the standard prior to check-in.) I can count on their framework code when I use it and concentrate on my business problem. I'm not writing boiler plate code again and again.
Spring 团队编写的代码经过设计、测试和遵循标准,比我编写的任何代码都要严格。(想象一下 Juergen Hoeller 因 Rod Johnson 的代码在签入前不符合标准而猛烈抨击。)当我使用它们时,我可以依靠他们的框架代码并专注于我的业务问题。我不会一次又一次地编写样板代码。
For me, Spring is more about an architectural template that acts as a guide for creating web apps. Some people might say that it's over-engineered, and for certain problems they're correct, but for the kind of problems that I'm faced with on a regular basis Spring is just the ticket.
对我来说,Spring 更像是一个架构模板,作为创建 Web 应用程序的指南。有些人可能会说它是过度设计的,对于某些问题他们是正确的,但对于我经常面临的那种问题,Spring 只是票。
As for the subquestions:
至于子问题:
What advantages do we have when using dependency injection frameworks?
我们在使用依赖注入框架时有什么优势?
Objects don't have to be responsible for managing their dependencies. Spring's application context is really just a big Factory Pattern from the GoF. It encourages you to design to an interface so you can change the implementation as needed. Your persistence interface might use a JDBC implementation today, Hibernate tomorrow; you might decide to auto generate a proxy to manage its transactional behavior. None of the client code has to change if you code to an interface.
对象不必负责管理它们的依赖项。Spring 的应用程序上下文实际上只是来自 GoF 的一个大工厂模式。它鼓励您设计接口,以便您可以根据需要更改实现。您的持久性接口今天可能使用 JDBC 实现,明天可能使用 Hibernate;您可能决定自动生成代理来管理其事务行为。 如果您对接口进行编码,则无需更改任何客户端代码。
The idea of describing classes with setter values and/or constructor parameters seems strange to me. Why do that? Because we can change the properties without recompiling the project? Is that all what we gain?
用 setter 值和/或构造函数参数描述类的想法对我来说似乎很奇怪。为什么要这样做?因为我们可以在不重新编译项目的情况下更改属性?这就是我们得到的全部吗?
Strange? You don't use properties or constructors in your code? You do it because that's the way most Java classes are written. Spring merely uses those mechanisms as a way to provide dependencies to the class.
奇怪的?您不在代码中使用属性或构造函数?您这样做是因为这是大多数 Java 类的编写方式。Spring 仅使用这些机制作为向类提供依赖项的一种方式。
Then, what objects should we describe in beans.xml ? All objects or only a few ?
那么,我们应该在 beans.xml 中描述哪些对象?所有对象还是只有几个?
Only the beans that have dependencies. I still call "new" for objects that are local to a particular method. They are created, used, and garbage collected in method scope. Those need not be under Spring's control.
仅具有依赖项的 bean。对于特定方法的本地对象,我仍然称其为“new”。它们在方法范围内被创建、使用和垃圾收集。那些不需要在 Spring 的控制之下。
回答by Nathan Hughes
You already have some good answers here, I want to address a couple specific questions you have:
您已经在这里有了一些很好的答案,我想解决您的几个具体问题:
The idea of describing classes with setter values and/or constructor parameters seems strange to me. Why do that? Because we can change the properties without recompiling the project? Is that all what we gain?
用 setter 值和/或构造函数参数描述类的想法对我来说似乎很奇怪。为什么要这样做?因为我们可以在不重新编译项目的情况下更改属性?这就是我们得到的全部吗?
It does seem weird at first but the point is that the container is in charge of plugging in dependencies for the objects, the objects themselves are not in charge of that. The scope of the objects configured in beans.xml is managed by Spring, so we don't have to worry so much about things being instantiated without the right dependencies (as long as the configuration is correct, I have been known to write unit tests to check that the spring configuration is doing what I want it to.)
乍一看确实很奇怪,但关键是容器负责插入对象的依赖项,对象本身并不负责。beans.xml中配置的对象的范围是由Spring管理的,所以我们不用太担心没有正确依赖的东西被实例化(只要配置正确,我就知道写单元测试检查弹簧配置是否按照我的意愿行事。)
Then, what objects should we describe in beans.xml ? All objects or only a few ?
那么,我们应该在 beans.xml 中描述哪些对象?所有对象还是只有几个?
The kinds of objects described in beans.xml are mostly components--controllers, services, data access objects, and things that they need like transaction managers, hibernate session factories, data sources, stuff like that. Domain objects are typically retrieved from data access objects or instantiated directly, because they don't have dependencies on anything but other domain objects (or on utility classes that are even more independent than domain classes).
beans.xml 中描述的对象种类主要是组件——控制器、服务、数据访问对象以及它们需要的东西,如事务管理器、休眠会话工厂、数据源等。域对象通常从数据访问对象中检索或直接实例化,因为它们不依赖于其他域对象(或比域类更独立的实用程序类)之外的任何对象。
回答by Adriaan Koster
Maybe you should not attempt to undertake 'Java enterprise development' without some idea about the basic architectural and design concerns? I suggest you either find an experienced co-worker who is willing to help you, or invest some more effort in reading those books, or otherwise follow a course.
也许您不应该在对基本架构和设计问题没有一些了解的情况下尝试进行“Java 企业开发”?我建议你要么找一个愿意帮助你的有经验的同事,要么花更多的精力去读那些书,或者学习一门课程。
In any case, there is no 'simple answer' to your question.
无论如何,您的问题没有“简单的答案”。
回答by Droo
Here's a good videogiven by Bob Lee and two of his under studies about Guice (Guice is a dependency injection framework like Spring). The first 10 or so minutes are about why Guice (or dependency injection) would be better than the alternative (Factories) so it's not all just about Guice.
这是Bob Lee 和他的两个正在研究的关于 Guice的很好的视频(Guice 是一个像 Spring 一样的依赖注入框架)。前 10 分钟左右是关于为什么 Guice(或依赖注入)比替代方案(工厂)更好的原因,所以这不仅仅是关于 Guice。
回答by Thomas Jung
Opinion: Figure out what problem you try to solve with DI and take a framework that fits best. Spring could add to much complexity for your problem.
意见:弄清楚你试图用 DI 解决什么问题,并采用最适合的框架。Spring 可能会增加您的问题的复杂性。
(One of the first articles about DI by Martin Fowler. I think the term DI was coined in this article.)
(Martin Fowler 撰写的关于 DI的第一篇文章之一。我认为 DI 一词是在本文中创造的。)
回答by akuhn
Dependency injection is a workaround for missing virtual classes!
依赖注入是缺少虚拟类的解决方法!
NB: if you don't know what virtual classes are, please refer to "Virtual classes, anyone?".
注意:如果您不知道什么是虚拟课程,请参阅“虚拟课程,有人吗?” .

