18

Possible Duplicates:
What is dependency injection?
What exactly is Spring for?

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?

Then, what objects should we describe in beans.xml? All objects or only a few?

The simplest answers are welcome

Ihor Patsian
  • 1,288
  • 2
  • 15
  • 25
EugeneP
  • 11,783
  • 32
  • 96
  • 142
  • 3
    Then what you are looking for is an article on the matter, not a SO answer. – Bozho Dec 30 '09 at 13:25
  • I'm not looking for an article on the matter AS I ALREADY TRIED THE BEST BOOKS published on the subject. I want to know the opinion of those who use it in everyday work. – EugeneP Dec 30 '09 at 13:28
  • Opinion: spring is good, makes things easy to develop and test. I doubt that's what you are looking for ;) – Bozho Dec 30 '09 at 13:31
  • 2
    btw, the books and the articles are written by people who use it in everyday work. So you probably missed something there. – Bozho Dec 30 '09 at 13:33
  • 2
    The original article on DI: http://martinfowler.com/articles/injection.html - if you can't get a grasp of the concept from this, then SO is not going to improve matters. – skaffman Dec 30 '09 at 13:39
  • You see the problem with books is that SIMPLE THINGS CAN BE EXPLAINED IN A FEW SENTENCES. Books are too long not because of little clarity and bad explanation techiques. – EugeneP Dec 30 '09 at 13:43
  • the books lack clarity and good explanation. – EugeneP Dec 30 '09 at 13:44
  • that's why I said "articles". The one given by skaffman, Thomas Jung, and me are short enough. – Bozho Dec 30 '09 at 13:44
  • @Bozho. I will definitely try that article 'cause it is written by Fowler. – EugeneP Dec 30 '09 at 13:46
  • and the one I gave in my answer is by the founder of the spring framework, so worth reading as well – Bozho Dec 30 '09 at 13:49
  • duplicate: http://stackoverflow.com/questions/130794/what-is-dependency-injection – Mauricio Scheffer Dec 30 '09 at 13:58
  • I WOULD NOT SAY MY QUESTION DUPLICATES that one. I ask mainly about SPRING. I don't need DI if I can use Spring without DI. But as books tell, DI is the foundation of Spring framework. – EugeneP Dec 30 '09 at 14:03
  • 1
    @EugeneP: no need to use caps. But it seems that you *do* need to learn what DI is about before asking about Spring in particular. – Mauricio Scheffer Dec 30 '09 at 14:15
  • @Mauricio Scheffer That is why I indicated the DI in my question header. Still your link is useful but it's not the duplicate. Please be more specific next time you give such an indicator. :) – EugeneP Dec 30 '09 at 14:18
  • @Mauricio Scheffer oh man. a .net developer closes a question. Can you read tags before posting something? I was asking about java. – EugeneP Dec 31 '09 at 09:25
  • 2
    @EugeneP: Petulance isn't going to get you anywhere, either. @Bozho may only have been here for 55 days, but he's gained 7k rep in that time, and the right to close questions as he sees fit. – skaffman Dec 31 '09 at 09:42
  • @skaffman, yes, you got even 26K. Be proud and happy new year to you. – EugeneP Dec 31 '09 at 10:21

10 Answers10

23

We use Dependency Injection (DI) to implement loose coupling. The choice of any particulary DI Container is not that important.

Every time you create an instance of a class by using the new keyword, 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).

This would look something like this in C# (but would be equivalent in 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.

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.

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 Principle by 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.

Mark Seemann
  • 225,310
  • 48
  • 427
  • 736
12

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.

Example

Without 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 SaleAction is coupled to CreditCardService and probably running your tests will generate fake payments.

Now the same example with 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 SaleAction is decoupled from any implementation, which means that in your test you can do SaleAction action = new SaleAction(new DummyBillingService());.

Hope that helps, there's also the article about DI, written by Martin Fowler that you can find here

Pablo Fernandez
  • 103,170
  • 56
  • 192
  • 232
  • effectively you are saying that DI frameworks, e.g. Spring, are overrated since it's trivial to replace dependencies with mocks in code without a framework. the creation of those mocks can be rather involved but I don't see any advantage in being able to swap them in and out for alternative mocks. – Adam Ralph Dec 30 '09 at 13:33
  • 4
    not relying on concrete implementations is at the core of OOP, not only of DI. – Bozho Dec 30 '09 at 13:37
  • I don't say that frameworks are overrated. DI is mandatory for unit testing, and unit testing is mandatory for software development. – Pablo Fernandez Dec 30 '09 at 13:37
  • @Adam - I think you misunderstood the answer. For a simple problem Spring can be overly complex. A hand coded DI/configuration can be simpler in this situation. But at some point it's worth to use a DI framework as the wiring gets to complicated and other features supported by Spring are needed. – Thomas Jung Dec 30 '09 at 13:40
  • 1
    DI is not mandatory for unit testing. – Bozho Dec 30 '09 at 13:40
  • 2
    @Pablo - "unit testing is mandatory for software development" - Well, I could not work without unit testing, but I don't think that even the majority of software has unit test coverage. – Thomas Jung Dec 30 '09 at 13:41
  • @Thomas and @Bozho, that phrase was overemphasized just to get to the point quickly. – Pablo Fernandez Dec 30 '09 at 13:44
  • DI is **not** primarily about testing. It's a nice side-effect, though. See http://ayende.com/Blog/archive/2007/08/18/Dependency-Injection-More-than-a-testing-seam.aspx http://ayende.com/Blog/archive/2007/08/21/Dependency-Injection-Applicability-Benefits-and-Mocking.aspx – Mauricio Scheffer Dec 30 '09 at 13:56
  • @Mauricio, if you are not doing unit testing, there's no real need for DI. – Pablo Fernandez Dec 30 '09 at 14:22
  • @Pablo: take a look at Mark Seeman's answer and Ayende's articles I linked above. That's what DI is about. – Mauricio Scheffer Dec 30 '09 at 14:45
  • @Mauricio: personal experience and 'crazy' Bob Lee (Guice creator) says otherwise. – Pablo Fernandez Dec 30 '09 at 16:31
3

Here's a good article explaining the ideas of spring. (By Rod Johnson, the founder of the Spring framework)

Bozho
  • 588,226
  • 146
  • 1,060
  • 1,140
3

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/

Ken Fox
  • 1,649
  • 8
  • 12
  • @Ken Fox. No, no. I will use Spring. DI was mentioned because it forms the basis of the Spring Framework. I'm not interested in DI, I am interested mainly in Spring functionality. but I need to know what lays in the base. – EugeneP Dec 30 '09 at 13:48
  • 1
    Spring has always been a huge framework, much more than DI. AOP has had equal billing since day one, as have the libraries. To say that Spring and Guice map one-to-one is as incorrect as saying the same for Spring MVC and Struts. Spring includes functionality equivalent to both and more. – duffymo Dec 30 '09 at 13:51
  • @Ken Fox. All right, I don't really understand yet AOP, I've read that it deals with "crosscutting concerns", things like logging that occur in virtually every method of the class. But tell me, all right, there's AOP. But it does not substitute DI, does it? – EugeneP Dec 30 '09 at 13:59
  • @duffymo: Who said Spring and Guice map one-to-one?! I suggested Guice because it only does DI and may be easier to understand if someone is only interested in DI. – Ken Fox Dec 30 '09 at 14:04
  • No, it's complementary. Did you learn anything from all those books you claim to have read? – duffymo Dec 30 '09 at 14:04
  • @Ken - I didn't suggest that you did, it's a response to the "huge framework" statement. I thought it implied that Spring had started life as a simple DI framework and ballooned in an uncontrolled way to something unwieldy. In my experience, there's a lot to Spring, but it's not necessary to understand or use all of it to get benefit from it. A la carte choices from Spring work well and play nicely with other technologies. – duffymo Dec 30 '09 at 14:06
  • 1
    @EugeneP: Don't pick a framework and then see what it does. There's an XP principle called YAGNI (You Ain't Gonna Need It) that has always been good to me. If you have a problem, find a solution, and if that brings you to a framework like Spring, at least you know where to start eating the elephant. – Ken Fox Dec 30 '09 at 14:06
  • @duffymo To answer your question, one should answer the question "What is learning and what 'to learn' means". I learned something from philosophy, so try to get me right ;) – EugeneP Dec 30 '09 at 14:07
  • I agree with Ken. It doesn't seem to me that Eugene is up to it yet. – duffymo Dec 30 '09 at 14:07
  • 1
    @Eugene - I think the bigger question here is "what reading is." I find it hard to believe that anyone could claim to have read the best books on any subject and come here to ask such an elementary question. What books did you read? Titles, please. – duffymo Dec 30 '09 at 14:09
  • @duffymo. Yes the question is simple but have you answered it? Many things in life seem simple when you do not need to explain [and CANNOT EXPLAIN] how it works and why. :) – EugeneP Dec 30 '09 at 14:14
  • @EugeneP - see how you like the modified answer. "cannot explain"? You be the judge. – duffymo Dec 30 '09 at 15:07
3

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?

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.)

Then, what objects should we describe in beans.xml ? All objects or only a few ?

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).

Nathan Hughes
  • 94,330
  • 19
  • 181
  • 276
2

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:

  1. dependency injection, which uses the Hollywood principle to help you keep interface and implementation separate;
  2. 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;
  3. 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.

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.

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.

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.

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.

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?

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.

Then, what objects should we describe in beans.xml ? All objects or only a few ?

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.

duffymo
  • 305,152
  • 44
  • 369
  • 561
1

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.

(One of the first articles about DI by Martin Fowler. I think the term DI was coined in this article.)

Thomas Jung
  • 32,428
  • 9
  • 84
  • 114
1

Here's a good video given 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.

Droo
  • 3,177
  • 4
  • 22
  • 26
1

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.

In any case, there is no 'simple answer' to your question.

Adriaan Koster
  • 15,870
  • 5
  • 45
  • 60
0

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?".

akuhn
  • 27,477
  • 2
  • 76
  • 91
  • 1
    The horror of C++ multiple virtual inheritance will be with me forever. I like that article, but you need a new name. DI frameworks now use annotations so they are almost indistinguishable from a language feature--until two different frameworks collide and the illusion is shattered. – Ken Fox Dec 30 '09 at 22:17