这可能是一个幼稚的问题。我目前正在学习Spring框架和依赖项注入(inject)。尽管DI的基本原理很容易掌握,但是为什么需要一个精巧的框架来实现它并不清楚。
考虑以下:
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>
加:
ApplicationContext context = new ClassPathXmlApplicationContext("sawmill.xml");
SawMill springSawMill = (SawMill)context.getBean("sawMill");
springSawMill.run();
诚然,这是一个人为的示例,并且对象关系更加复杂,存储XML文件比以编程方式写入XML文件更为有效,但是肯定有更多的东西吗?
(我知道Spring框架还不止于此,但我正在考虑需要一个DI容器。)
在第一个示例中,在中间更改依赖项也很简单:
// gotta chop it faster
saw = new ChainSaw();
sawMill.setSaw(saw);
sawMill.run();
最佳答案
我有完全相同的问题,并通过以下方式回答:
当然,您可以按照“然后您可以做:...”中的描述进行操作(我们将其称为“A类”)。但是,这会将A类耦合到HandSaw,或者耦合到SawMill类需要的所有依赖项。为什么将A耦合到HandSaw-或者,如果您采取更现实的情况,为什么要将我的业务逻辑耦合到DAO层所需的JDBC连接实现?
然后,我提出的解决方案是“然后将依赖关系再进一步一步”-好的,所以现在我的观点与JDBC连接耦合了,在这里我应该只处理HTML(或者选择Swing,选择您喜欢的风格)。
由XML(或JavaConfig)配置的DI框架通过仅允许您“获得所需的服务”来解决此问题。您不必关心它是如何初始化的,它需要做什么工作-您只需获取服务对象并激活它即可。
另外,您对“加号”有一个误解(在其中执行SawMill springSawMill = (SawMill)context.getBean("sawMill"); springSawMill.run();
)-您不需要从上下文中获取sawMill bean-应该通过以下方式将sawMill bean注入(inject)到您的对象中(类A): DI框架。因此,您不用去找... getBean(...),而是去“sawMill.run()”,而不在乎它的来源,初始化者和初始化方式。就您所关心的而言,它可以直接转到/dev/null或测试输出,或使用真正的CnC引擎...重点是-您不在乎。您所关心的只是您很小的A类小类,应该按契约(Contract)做的事-激活锯木厂。