Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
106 views
in Technique[技术] by (71.8m points)

java - Understanding the need for a DI framework

This might be a naive question. I'm currently learning the Spring framework and dependency injection. While the basic principle of DI is rather easy to grasp, it's not immediately obvious why you need an elaborate framework to implement it.

Consider the following:

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");
    }
}

Then you could simply do:

Saw saw = new HandSaw();
SawMill sawMill = new SawMill();
sawMill.setSaw(saw);
sawMill.run();

Which would be equivalent to:

<bean id="saw" class="HandSaw"/>

<bean id="sawMill" class="SawMill">
   <property name="saw" ref="saw"/>
</bean>

plus:

ApplicationContext context = new ClassPathXmlApplicationContext("sawmill.xml");
SawMill springSawMill = (SawMill)context.getBean("sawMill");
springSawMill.run();

Granted, this is a contrieved example, and with more complex object relationships it might be more efficient to stash up an XML file than writing it programmatically, but surely there must be more to it than that?

(I know the Spring framework is more than that, but I'm thinking of the need for a DI container.)

In the first example it would also be trivial to change dependencies midstream:

// gotta chop it faster
saw = new ChainSaw();
sawMill.setSaw(saw);
sawMill.run();
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

I've had the exact same question, and it was answered by this:
Granted, you could do what you've described in "Then you could simply do:..." (let's call that "class A"). However, that would couple class A to HandSaw, or to all dependencies needed from class SawMill. Why should A be coupled to HandSaw - or, if you take a more realistic scenario, why should my business logic be coupled to the JDBC connection implementation needed for the DAO layer?
The solution I proposed then was "then move the dependencies one step further" - ok, so now I've got my view coupled to JDBC connection, where I should only deal with HTML (or Swing, pick your flavor).

The DI framework, configured by an XML (or JavaConfig) solves this by letting you just "get the needed service". You don't care how it's initialized, what it needs to work - you just get the service object and activate it.

Also, you have a misconception there regarding the "plus:" (where you do SawMill springSawMill = (SawMill)context.getBean("sawMill"); springSawMill.run();) - you don't need to get the sawMill bean from the context - the sawMill bean should've been injected into your object (class A) by the DI framework. so instead of ...getBean(...), you'd just go "sawMill.run()", not caring where it came from, who initialized it and how. For all you care, it could go straight to /dev/null, or test output, or real CnC engine... The point is - you don't care. All you care is your tiny little class A which should do what it's contracted to do - activate a saw mill.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...