11

See the top answer to this question: What exactly is Spring Framework for?

Im at loss as to what the problem is, and why Springs solution of putting specifying what implementation of the interface to use inside an XML file (or using annotations) is better than simply having a line of code instantiate the correct interface?

EDIT: As I wrote in one of my comments, Im genuinely trying to understand the benefits. I want to understand why Spring is useful. Im not advocating not using Spring or trying to provide reasons not to, rather, Im searching for reasons and trying to understand why it should be used. This post was not meant to encourage debate but straightforward and technical answers. I have now selected the shortest and most illustrative answer as the correct answer. I must say Im a bit surprised that the question was closed.

Community
  • 1
  • 1
fred
  • 1,812
  • 3
  • 37
  • 57
  • Possible duplicate: http://stackoverflow.com/questions/871405/why-do-i-need-an-ioc-container-as-opposed-to-straightforward-di-code – Mark Seemann Dec 30 '11 at 09:35
  • Possible duplicate: http://stackoverflow.com/questions/130794/what-is-dependency-injection – Mark Seemann Dec 30 '11 at 09:36
  • Related: http://stackoverflow.com/questions/5667801/arguments-against-inversion-of-control-containers/5668093#5668093 – Mark Seemann Dec 30 '11 at 09:37
  • Possible duplicate: http://stackoverflow.com/questions/2512316/ioc-dependency-injection-please-explain-code-versus-xml – Mark Seemann Dec 30 '11 at 09:38
  • @MarkSeemann I appreciate the effort to provide a list of other similar questions but I dont think any of those are duplicates. – fred Dec 30 '11 at 10:17

5 Answers5

6

If class A uses class B, DI takes the responsibility of providing the class B to the class A. It is commonly used for testing where Spring would provide a different B class (mock for example).

Sure, you can do all this yourself, but usually it's less work if you let Spring (or any other DI framework) do this for you.

milan
  • 11,872
  • 3
  • 42
  • 49
  • 1
    If you want to use different implementations of an interface in a class depending on the context, you can use a setter method or different constructors in order to specify which one you want to use. I still dont see the need for Spring. – fred Dec 30 '11 at 09:38
  • http://stackoverflow.com/questions/871405/why-do-i-need-an-ioc-container-as-opposed-to-straightforward-di-code – Petar Minchev Dec 30 '11 at 09:40
  • 1
    there's nothing Spring does that you can't do yourself, it's just that it's less work if you let spring. – milan Dec 30 '11 at 09:41
  • 1
    How is adding Spring to a project, setting it up, and configuring and managing all its XML files easier than simply having a constructor or setter that receives what to use? – fred Dec 30 '11 at 09:59
  • It doesn't have to be XML, it can be with annotations, @ Autowire + @ Component for example. If you have a class or two then it probably doesn't make sense, but which project has only 2-3 classes? :) – milan Dec 30 '11 at 10:06
  • 1
    Yeah but why not just use setters and constructors to allow developers to send class B to class A? (Or class C if B and C are different implementations of the same interface) – fred Dec 30 '11 at 10:19
  • The amount of code you'd have to write in that case would be much more compared to few annotations. – milan Dec 30 '11 at 10:23
  • 1
    Adding Spring, setting it up, and using it adds a lot of overhead which is arguably worse than having "normal", explicit, declarative code? To me it seems that simply using the usual constructor and setter approach is way easier =/ – fred Dec 30 '11 at 10:43
2

The main problem solved by dependency injection is unit-testing. Suppose you have a DoorOpeningService which depends on a NuclearPlant. To unit-test the DoorOpeningService, you would need to have a NuclearPlant (which is rather costly and hard to setup just to test opening doors).

If the code of DoorOpeningService is like the following:

public class DoorOpeningServiceImpl implements DoorOpeningService {

    private NuclearPlant plant;

    public DoorOpeningServiceImpl() {
        this.plant = SomeNamingService.lookup("nuclearPlant");
    }

    public void openDoors() {
        int electricity = plant.getSomeElectricity();
        ...
    }
}

The DoorOpeningService is very hard to unit-test.

Dependency injection allows giving the NuclearPlant to the DoorOpeningService. So, instead of needing a real nuclear plant, you can give it a fake one, which always gives some electricity without needing all the real nuclear plant infrastructure. And the DoorOpeningService is thus much more easier to test:

public class DoorOpeningServiceImpl implements DoorOpeningService {

    private NuclearPlant plant;

    // The plant is injected by constructor injection
    public DoorOpeningServiceImpl(NuclearPlant plant) {
        this.plant = plant;
    }

    public void openDoors() {
        int electricity = plant.getSomeElectricity();
        ...
    }
}

Having a framework inject dependencies for you is easier, and also allows for additional aspects (interceptors if you prefer) to be added. For example, Spring can inject, instead of your NuclearPlant implementation, a proxy to this implementation that makes sure, for every call to the plant, that a transaction is open, or that the caller is authorized to call its methods, or that statistics are gathered to help diagnosing slow parts in the application.

JB Nizet
  • 678,734
  • 91
  • 1,224
  • 1,255
  • He is asking why he should use Spring, when he can do the following: new DoorOpeningServiceImpl(new NuclerPlant()). – Petar Minchev Dec 30 '11 at 09:43
  • Sorry, but I dont see what this has to do with Spring? This is exactly my point, if the dooropeningserviceimpl should be able to use different plants, then just use setters or constructors to allow other classes to specify which plant the dooropeningserviceimpl should use. No need for Spring? – fred Dec 30 '11 at 09:47
  • See the last part of my answer. Also, Spring beans are singleton by default. Manual dependency injection like you showed instantiate a new NuclearPlant each time one is needed, which might not be a very good idea. – JB Nizet Dec 30 '11 at 09:49
  • How is adding Spring to a project, setting it up, and configuring and managing all its XML files easier than simply having a constructor or setter that receives what to use? Achieving all those things you mention at the end of you answer is easily done without Spring? Just make a impl/subclass of Plant with the extra functionality? As for singletons, I dont see how that in itself is enough to justify using Spring. – fred Dec 30 '11 at 10:03
  • @fred imagine you make a web app pointing to a DB your client manages. Some day, they phone you to change the app to point to another DB because the first one crashed. The next day, they decide to point to first DB which has been fixed. Other day both DB are broken and they request you to put a 3rd one. If you were to recompile each time, and redeploy (this requires sysadmins time too) it would be a mess. So you detect the high modifiability and implement DI based on configuration files, or code a GUI to allow them to swicht DB address. So... – Mister Smith Dec 30 '11 at 10:04
  • ...using a framework to solve this is good because if you need in the future a similar solution for other feature of your app, you can reuse it in a similar way. – Mister Smith Dec 30 '11 at 10:05
  • @fred: nobody forces you to use Spring. In my experience, it's a huge time-saver, but YMMV. When a new developer is hired, he quickly understands how the application works, because a well-known framework is used rather than a proprietary one. I've seen lots of proprietary frameworks reinventing the wheel, and all of them sucked. Moreover, annotations are the preferred way to use Spring, nowadays. XML files are typically very small. – JB Nizet Dec 30 '11 at 10:09
  • @Mister Smith In this case, I can see the use. But this is arguably not a problem that justifies using Spring for just about everything, like a lot of adherents seem to do and claim is good and necessary? If you look at the example of having a DAO interface and two different implementations of that interface, one for files and one for DB, then just using a setter or constructor to specify whichever implementation is arguably way easier than doing it via Spring? – fred Dec 30 '11 at 10:10
  • @JBNizet Im genuinely trying to understand the benefits. I want to understand why Spring is useful, but I just cant. Im not advocating not using Spring or trying to provide reasons not to, rather, Im searching for reasons and trying to understand why it should be used. – fred Dec 30 '11 at 10:13
  • Well, try reimplementing the dependency injection (if you find it useful but can do it yourself), then try to reimplement the AOP infrastructure to be able to make services transactional, secure, etc., then reimplement the transaction management and make sure it can be used with plain JDBC, JPA, JDO, Hibernate, etc. and that an XA transaction manager can be plugged in if necessary. In two years, when you finish, you'll have the core of what a typical Spring application uses. – JB Nizet Dec 30 '11 at 10:22
  • "Dependency injection is basically providing the objects that an object needs (its dependencies) instead of having it construct them itself." Your answers have so far not made me understand why using Spring DI is better than simply sending what a class needs through constructors or setters =( – fred Dec 30 '11 at 10:37
  • Because constructing the dependencies yourself is complex, especially when you have to account for singletons/prototypes, transactional aspects, security aspects, logging aspects, circular dependencies, life-cycle callbacks, configuration, etc. Rather than having each project implementing all these features again and again, you use a well-known and tested framework/library to do it for you. The reusability principle. The principle without which we would all code in assembler. – JB Nizet Dec 30 '11 at 10:45
  • @fred if IOC is all you need, then DIY is an option. The code will be much cleaner and the app will be smaller in size. I'm the #1 anti-framework guy at job because they put a lot of crap which is rarely used. Just use Spring if you really need it. – Mister Smith Dec 30 '11 at 10:49
  • @JBNizet can you give a simple, concrete example of a case where using setters or constructors to provide a class with what it needs is a suboptimal approach compared to using Spring considering all those things you just mentioned? – fred Dec 30 '11 at 10:55
  • Well, each time I want to inject a transactional service into a web controller. Being able to simply add a @Transactional annotation to my service class or method to make it transactional is a sufficiently good reason. Or each time I want to have inject a JPA EntityManager in a DAO and have all the work done with the entity manager be part of the transaction open by Spring when the calling service was invoked. Or each time I want to have a reference to a remote service in a rich client application, and have a proxy automatically cache the result of the remote service call. – JB Nizet Dec 30 '11 at 11:10
1

Im at loss as to what the problem is,

The problem is basically how to swap implementations dinamically at runtime or via configuration files.

why Springs solution of putting specifying what implementation of the interface to use inside an XML file is better than simply having a line of code instantiate the correct interface

It is better because XML files can be tweaked without recompiling and redeploying the whole app.

This is one of the best articles on DI out there, you might want to take a look at it:
http://martinfowler.com/articles/injection.html

Mister Smith
  • 27,417
  • 21
  • 110
  • 193
  • He is asking what is `Dependency Injection` for. You can use DI without xml, by using annotations. – Petar Minchev Dec 30 '11 at 09:30
  • And the main point is not to swap implementations at runtime. BTW, Spring resolves all dependencies once and for all, at startup time. – JB Nizet Dec 30 '11 at 09:39
  • If that is the sole benefit, then arguably using Spring is not worth it. Adding Spring to a project, setting it up and maintaining all the XML files most likely takes more time than recompiling the app. Also since Spring can also use annotations this is not a valid reason in that case. – fred Dec 30 '11 at 09:41
  • @JB Nizet read the whole sentence, it has a big or inside. – Mister Smith Dec 30 '11 at 09:45
  • @fred I know Spring is much more than that. I wasn't talking about Spring but about DI in general. – Mister Smith Dec 30 '11 at 09:46
  • @Mister Smith: even with the or, that's not the point. 99% of application Spring beans have only 1 implementation. – JB Nizet Dec 30 '11 at 09:53
  • @fred that benefit alone may be worth it for large programs. – Thorbjørn Ravn Andersen Dec 30 '11 at 10:00
1

The benefit of using Dependency Injection comes when you have code like the following

Interface i;
if (useA) {
  i = new A();
} else if (useB) {
  i = new B();
} else if (useC) {
  i = new C();
}
i.call();

You have several different kinds of Interface and you need to choose which one to use when you run the program because you don't know which one to use when you write the program. This means that useA, useB and useC somehow needs to be found out when starting the program. A typical approach is to have detection code or a property file which is loaded, setting these values.

Also the "who is to actually do it" part may be hard to put for e.g. web applications which primarily consists of code being called from the outside.

Dependency Injection formalizes this like:

@Injection Interface i;
i.call();

Spring makes the i automatically initialized, so you don't have to worry in your code about flags or where to put the factory, in a standard way. This separation of handling A,B,C from the actual code has proven to create very clean code.


EDIT: when revisiting this question I understood that the question is actually "why use dependency injection when you can do the same with getters and setters?".

In my opinion the important thing to realize is that you cannot do anymore with dependency injection than you can with getters and setters, but the only place you can use getters and setters is in the code that creates the new object. In Java that is the new statement. In other words that code needs to know all the details, and it frequently doesn't. This is why we have factories of factories - as a mean to move the decision process closer to runtime - and dependency injection is essentially just that. A factory framework. But the crucial thing to notify is that it allows you to detach the configuration part from the part doing work and put it elsewhere.

Thorbjørn Ravn Andersen
  • 73,784
  • 33
  • 194
  • 347
  • Why would anyone code the way you showed in your example? This is what setters are for? Using setters and constructors to specify from the outside what interface implementation to use produces the same result using normal code? – fred Dec 30 '11 at 10:16
  • @fred, this was a simplified answer. This might as well have been a call to a factory. _Somewhere_ you essentially have to have that code choosing between A, B, and C. Where do _you_ put it? – Thorbjørn Ravn Andersen Dec 30 '11 at 10:23
  • Lets say I have an interface for listing Users. One implementation of that interface uses a DB, another implementation uses a file to get users for the list. Lets say I have a view that uses the interface. In that view i simply instantiate the correct one, and use that. If I used Spring, I would specify which to use in an XML file. What is the difference, why is the Spring approach better? – fred Dec 30 '11 at 10:29
  • So where is your code put that _choose_ which one to use? What if you must delay the choice to when the program is actually run because you do not know when you write the program what implementation the user actually NEEDS? – Thorbjørn Ravn Andersen Dec 30 '11 at 10:43
  • Then you could add functionality for setting it dynamically, or use config files. Or use Spring I guess. Is this the benefit of using Spring DI then? Being able to e.g. decide what implementation of an interface to use at runtime through editing an XML file? – fred Dec 30 '11 at 10:52
  • Yes, Dependency Injection is about being able to decide at a later time than _when you compile your program_ which implementation to use (and whether to use a singleton and much more). Spring is just one that allows for this. Personally I like the Guice approach to DI better. – Thorbjørn Ravn Andersen Dec 30 '11 at 10:54
  • "Dependency injection is basically providing the objects that an object needs (its dependencies) instead of having it construct them itself" and "Dependency Injection is about being able to decide at a later time than when you compile your program which implementation to use (and whether to use a singleton and much more)" = not even close to similar, so I dont know if you are correct in making that statement. And while I see that being able to use config files to specify such things dynamically has value, I fail to see how this is important in most contexts where Ive seen Spring being used. – fred Dec 30 '11 at 11:02
  • 1
    You asked why it was better to use DI instead of just writing a code snippet. The reason is that it solves some real problems when you write code earlier than you know what exact configuration the customer needs. – Thorbjørn Ravn Andersen Dec 30 '11 at 11:22
0

Im at loss as to what the problem is, and why Springs solution of putting specifying what implementation of the interface to use inside an XML file (or using annotations) is better than simply having a line of code instantiate the correct interface?

First of all, the config looks the same (and can be found in the same place) regardless of whether your app is a web application, desktop, etc. That's a minor advantage, but I've found it rather handy when inheriting a project.

Second, you often want some kind of externalization of the config - like changing URLs to external services, timeout limits etc without rebuilding the app, which means that you're going to wind up with a config file regardless. And it just so happens that Spring's config format is very powerful - except for being able to hardcode stuff (like saying "bean fooDao is to be an instance of JpaFooDao using this here database"), you can also refer to Java constants as well as system properties (with ${propertyName} syntax), perform JNDI lookups, add aspect wrappers which for instance can make stuff transactional without coding, and more. All of which you could make yourself, but not without a considerable amount of work.

I hate XML as much as anyone, but I've never found Spring's XML config to very bothersome (at least not when offloaded with annotations).

gustafc
  • 28,465
  • 7
  • 73
  • 99