Java 了解DI框架的需求
这可能是一个天真的问题。我目前正在学习Spring框架和依赖注入。虽然DI的基本原理很容易掌握,但您为什么需要一个复杂的框架来实现它,这一点并不明显 考虑以下几点:Java 了解DI框架的需求,java,spring,dependency-injection,Java,Spring,Dependency Injection,这可能是一个天真的问题。我目前正在学习Spring框架和依赖注入。虽然DI的基本原理很容易掌握,但您为什么需要一个复杂的框架来实现它,这一点并不明显 考虑以下几点: public abstract class Saw { public abstract void cut(String wood); } public class HandSaw extends Saw { public void cut(String wood) { // chop it
public abstract class Saw
{
public abstract void cut(String wood);
}
public class HandSaw extends Saw
{
public void cut(String wood)
{
// chop it up
}
}
public class ChainSaw extends Saw
{
public void cut(String wood)
{
// chop it a lot faster
}
}
public class SawMill
{
private Saw saw;
public void setSaw(Saw saw)
{
this.saw = saw;
}
public void run(String wood)
{
saw.cut("some wood");
}
}
然后你可以简单地做:
Saw saw = new HandSaw();
SawMill sawMill = new SawMill();
sawMill.setSaw(saw);
sawMill.run();
这相当于:
<bean id="saw" class="HandSaw"/>
<bean id="sawMill" class="SawMill">
<property name="saw" ref="saw"/>
</bean>
诚然,这是一个精心设计的示例,对于更复杂的对象关系,隐藏XML文件可能比以编程方式编写XML文件更有效,但肯定还有更多的内容吗
(我知道Spring框架不止这些,但我正在考虑是否需要DI容器。)
在第一个示例中,在中游更改依赖项也很简单:
// gotta chop it faster
saw = new ChainSaw();
sawMill.setSaw(saw);
sawMill.run();
如果硬编码插入的类,则需要该类在编译时可用。使用配置文件,您可以在运行时更改使用过的saw(在您的示例中),而无需重新编译,甚至可以使用从刚刚放置在类路径中的新jar中获取的saw。如果值得的话,额外的复杂性取决于您必须解决的任务。重要的是要理解Spring基本上是两件事,一件是建立在另一件之上的:
所有这些助手都使用(1)将它们连接在一起。我有一个完全相同的问题,答案是:
当然,你可以做你在“那么你可以简单地做:…”(我们称之为“A类”)中描述的事情。然而,这会将类A耦合到手锯,或者耦合到锯木厂类所需的所有依赖项。为什么要将A耦合到HandSaw?或者,如果采用更现实的场景,为什么要将我的业务逻辑耦合到DAO层所需的JDBC连接实现?
我当时提出的解决方案是“然后将依赖项进一步移动”——好的,现在我已经将我的视图与JDBC连接相耦合,我应该只处理HTML(或者Swing,选择您的风格) 由XML(或JavaConfig)配置的DI框架通过让您“获得所需的服务”来解决这个问题。您不在乎它是如何初始化的,也不在乎它需要做什么——您只需要获取服务对象并激活它
另外,您对“plus”有一个错误的概念:(
SawMill-springSawMill=(SawMill)context.getBean(“SawMill”);springSawMill.run();
)-您不需要从上下文获取锯木厂bean-锯木厂bean应该已经被DI框架注入到您的对象(类a)中。因此,您只需使用“sawMill.run()”,而不必使用…getBean(…),不管它来自何处、是谁初始化的以及如何初始化的。不管怎么说,它可以直接转到/dev/null,或者测试输出,或者真正的CnC引擎。。。关键是——你不在乎。你所关心的只是你的小小的类A,它应该做它约定要做的事情——激活锯木厂。我通常不关心XML或基于反射的DI,因为在我的用例中,它增加了不必要的复杂性。相反,我通常会选择某种形式的手动DI,对我来说,这似乎更自然,并且具有大多数好处
public class SawDI{
public Saw CreateSaw(){
return new HandSaw();
}
public SawMill CreateSawMill(){
SawMill mill = new SawMill();
mill.SetSaw(CreateSaw());
return mill;
}
}
// later on
SawDI di = new SawDI();
SawMill mill = di.CreateSawMill();
这意味着我仍然集中了耦合,并具有所有的优势,而不依赖于更复杂的DI框架或XML配置文件。最重要的一件事(如果不是全部的话)DI容器/库还为您带来了截取通过DI创建的所有实例的方法的可能性。Spring帮助您理解甚至鼓励DI模型。然而,我不相信你一定要有春天 您可以使用Java的配置文件进行调试、重构和代码分析 我建议您将这些java配置文件放在另一个包中,但它们在其他方面等同于XML配置文件。如果这很重要,您甚至可以动态加载这些文件 诚然,这是一个精心设计的示例,对于更复杂的对象关系,隐藏XML文件可能比以编程方式编写XML文件更有效,但肯定还有更多的内容吗 我认为将“连接”放在配置文件中比在代码中手动执行更有意义,原因如下:
控制器
类,该类获得一个服务
类,该类包含您的业务逻辑,该类使用DAO
从数据库获得Saw
s,该类将数据源
注入数据库,等等),手动连接协作者是乏味的,需要几十行代码,这些代码除了连接之外什么也不做李>
Spring有三个同样重要的功能:
public class SawDI{
public Saw CreateSaw(){
return new HandSaw();
}
public SawMill CreateSawMill(){
SawMill mill = new SawMill();
mill.SetSaw(CreateSaw());
return mill;
}
}
// later on
SawDI di = new SawDI();
SawMill mill = di.CreateSawMill();
SawMill sawMill = new SawMill(new HandSaw());
sawMill.run();