263

So, I'm starting a brand-new project in Java, and am considering using Spring. Why am I considering Spring? Because lots of people tell me I should use Spring! Seriously, any time I've tried to get people to explain what exactly Spring is or what it does, they can never give me a straight answer. I've checked the intros on the SpringSource site, and they're either really complicated or really tutorial-focused, and none of them give me a good idea of why I should be using it, or how it will make my life easier. Sometimes people throw around the term "dependency injection", which just confuses me even more, because I think I have a different understanding of what that term means.

Anyway, here's a little about my background and my app :

Been developing in Java for a while, doing back-end web development. Yes, I do a ton of unit testing. To facilitate this, I typically make (at least) two versions of a method : one that uses instance variables, and one that only uses variables that are passed in to the method. The one that uses instance variables calls the other one, supplying the instance variables. When it comes time to unit test, I use Mockito to mock up the objects and then make calls to the method that doesn't use instance variables. This is what I've always understood "dependency injection" to be.

My app is pretty simple, from a CS perspective. Small project, 1-2 developers to start with. Mostly CRUD-type operations with a a bunch of search thrown in. Basically a bunch of RESTful web services, plus a web front-end and then eventually some mobile clients. I'm thinking of doing the front-end in straight HTML/CSS/JS/JQuery, so no real plans to use JSP. Using Hibernate as an ORM, and Jersey to implement the webservices.

I've already started coding, and am really eager to get a demo out there that I can shop around and see if anyone wants to invest. So obviously time is of the essence. I understand Spring has quite the learning curve, plus it looks like it necessitates a whole bunch of XML configuration, which I typically try to avoid like the plague. But if it can make my life easier and (especially) if make it can make development and testing faster, I'm willing to bite the bullet and learn Spring.

So please. Educate me. Should I use Spring? Why or why not?

9
  • 14
    I think you really need to try it out for a while for yourself to see if you like it and if its suitable for your project. Personally I hate it.
    – Richard
    Commented Jul 13, 2011 at 22:18
  • 1
    While you can use XML or annotations; keep in mind that Spring takes a convention over configuration mentality. It's not necessarily a checklist of items you have to address. Commented Jul 13, 2011 at 22:23
  • 20
    While it's true that this question is rather broad, I think it should remain open. I read it as "What benefits does Spring offer for a medium-sized project?", and that's a good question.
    – sleske
    Commented Oct 21, 2012 at 9:32
  • 2
    I highly recommend reading my favorite technical book: Spring in Action, Third Edition by Craig Walls. It's a great read and will change the way you program.
    – alfredaday
    Commented Mar 19, 2014 at 2:06
  • 4
    Considering Enterprise Java, it's easier to answer what Spring doesn't do...
    – Random42
    Commented Mar 10, 2015 at 21:10

7 Answers 7

124

What does the Spring framework do? Should I use it? Why or why not?

Spring is a framework that helps you to "wire" different components together. It is most useful in cases where you have a lot of components and you might decide to combine them in different ways, or wish to make it easy to swap out one component for another depending on different settings or environments.

This is what I've always understood "dependency injection" to be.

I would suggest a different definition:

"Design your objects so that they rely on an outside force to supply them with what they need, with the expectation that these dependencies are always injected before anybody asks them to start doing their usual jobs."

Compare that against: "Each object is responsible for going out and finding everything and everybody it needs as it starts up."

it looks like it necessitates a whole bunch of XML configuration

Well, most of the XML (or annotation-based) stuff is telling Spring stuff like:

  • When someone asks for "HammerStore", I want you to create an instance of example.HammerStore and return it. Cache the instance for next time, since there only needs to be one store.
  • When someone asks for "SomeHammer", I want you to ask yourself for a "HammerStore", and return the result of the store's makeHammer() method. Do not cache this result.
  • When someone asks for "SomeWrench", I want you to create an instance of example.WrenchImpl, Use the configuration setting gaugeAmount and put it into the instance's setWrenchSize() property. Do not cache the result.
  • When someone asks for "LocalPlumber", I want to you create an instance of example.PlumberImpl. Put the string "Pedro" into its setName() method, put a "SomeHammer" into its setHammer() method, and put a "SomeWrench" into its setWrench() method. Return the result, and cache the result for later since we only need one plumber.

In this way, Spring lets your connect components, label them, control their lifecycles/caching, and alter behavior based on configuration.

To facilitate [testing] I typically make (at least) two versions of a method : one that uses instance variables, and one that only uses variables that are passed in to the method.

That sounds like a lot of overhead for not a lot of benefit for me. Instead, make your instance variables have protected or package visibility, and locate the unit tests inside the same com.mycompany.whatever package. That way you can inspect and change the instance variables whenever you want during testing.

0
74

First, what is dependency injection?

Simple. You have a class, it has a private field (set to null) and you declare a public setter that provides the value for that field. In other words, the dependency of the class (the field) is being injected by an external class (via the setter). That's it. Nothing magical.

Second, Spring can be used without XML (or very little)

If you dive in with Spring 3.0.5.GA or higher then you can use the dependency injection support from JDK6+. This means that you can wire up dependencies using the @Component and @Resource annotations.

Why use Spring at all?

Obviously, dependency injection promotes very easy unit testing since all your classes have setters for the important dependencies and these can be easily mocked using your favourite mocking framework to provide the required behaviour.

That aside, Spring also provides a lot of templates which act as base classes to make using the JEE standard technologies a breeze to work with. For example, the JdbcTemplate works well with JDBC, the JpaTemplate does good things with JPA, JmsTemplate makes JMS pretty straightforward. The RestTemplate is simply awesome in it's simplicity. For example:

RestTemplate restTemplate = new RestTemplate();
MyJaxbObject o = restTemplate.getForObject("https://secure.example.org/results/{param1}?param2={param2}",MyJaxbObject.class,"1","2");

and you're done. The parameters are injected and you just need to provide JAXB annotations for MyJaxbObject. That should take no time at all if you've auto-generated them from an XSD using the Maven JAXB plugin. Note that there was no casting going on there, nor was there a need to declare a marshaller. It's all done for you.

I could burble on forever about the wonders of Spring, but maybe the best thing to do is try out a simple code spike where you attempt to wire up a RESTful web service to pump out data from an injected DAO that supports transactions.

2
  • 4
    yeah RestTemplate is pretty awesome. I've got like 100 lines of code that I can throw away and replace with 2-3 lines.
    – Kevin
    Commented Jul 14, 2011 at 5:42
  • 14
    To nitpick: Dependency Injection also includes the constructor-based approach. You don't necessarily need to have setters.
    – Darien
    Commented Jul 15, 2011 at 18:31
31

First of all, your understanding of dependency injection is not fundamentally wrong, but quite different from what most people mean when they use the term. What you describe is a rather strange and unconventional way to achieve testability. I'd advise you to move away from it, as other developers will be rather puzzled by that kind of code.

Dependency injection as it's generally understood (and implemented by Spring) means that the dependencies a class has (e.g. a JDBC Datasource) are not fetched by the class itself, but "injected" by a container when the instance is created. So you don't have have two versions of every method that uses the Datasource; instead, you have one dependency injection configuration where the "real" Datasource is injected and one where a mock is injected. Or, if the injection happens via the constructor or a getter, test code can do the injection explicitly.

Second, Spring is not just dependency injection, though that's its core functionality. It also provides declarative transactions, job scheduling, authentication, and a bunch of other functionality (including a fully-fledged MVC web framework) that you may need. There are other frameworks that provide the same functionality, but other than Spring, only Java EE has them all integrated.

1
  • OP understands DI perfectly well
    – Basilevs
    Commented Jun 15, 2015 at 8:12
20

For why you want to use Spring, you can read this article (archived).

In summary:

  • J2EE applications tend to contain excessive amounts of "plumbing" code. Many code reviews repeatedly reveal a high proportion of code that doesn't do anything: JNDI lookup code, Transfer Objects, try/catch blocks to acquire and release JDBC resources. . . . Writing and maintaining such plumbing code proves a major drain on resources that should be focused on the application's business domain.

  • Many J2EE applications use a distributed object model where this is inappropriate. This is one of the major causes of excessive code and code duplication. It's also conceptually wrong in many cases; internally distributed applications are more complex than co-located applications, and often much less performant. Of course, if your business requirements dictate a distributed architecture, you need to implement a distributed architecture and accept the trade-off that incurs (and Spring offers features to help in such scenarios). But you shouldn't do so without a compelling reason.

  • The EJB component model is unduly complex. EJB was conceived as a way of reducing complexity when implementing business logic in J2EE applications; it has not succeeded in this aim in practice.

  • EJB is overused. EJB was essentially designed for internally distributed, transactional applications. While nearly all non-trivial applications are transactional, distribution should not be built into the basic component model.

  • Many "J2EE design patterns" are not, in fact, design patterns, but workarounds for technology limitations. Overuse of distribution, and use of complex APIs such as EJB, have generated many questionable design patterns; it's important to examine these critically and look for simpler, more productive, approaches.

  • J2EE applications are hard to unit test. The J2EE APIs, and especially, the EJB component model, were defined before the agile movement took off. Thus their design does not take into account ease of unit testing. Through both APIs and implicit contracts, it is surprisingly difficult to test applications based on EJB and many other J2EE APIs outside an application server. Yet unit testing outside an application server is essential to achieve high test coverage and to reproduce many failure scenarios, such as loss of connectivity to a database. It is also vital to ensuring that tests can be run quickly during the development or maintenance process, minimizing unproductive time waiting for redeployment.

  • Certain J2EE technologies have simply failed. The main offender here is entity beans, which have proven little short of disastrous for productivity and in their constraints on object orientation.

0
16

Used to be we wrote simple, efficient, fast applications and web services using just core Java, Servlets and JSP, html and xml, JDBC API. It was good enough; JUnit was a good tool to test. We rested easy that our code worked.

Hibernate came along to simplify SQL and enable true mapping of Database tables with Java objects, allowing hierarchical relationships to be reflected in the Object Relations Mapping or ORM as we call it. I loved it. Especially that we did not have to map the ResultSet back into a Java object or data type.

Struts came along to add the Model View Controller pattern to our Web apps, it was good.

EJBs were a huge overhead and pain and annotations made code look like chicken scratch and now Spring got sprung on us innocent folks. It just seems overdoing to me.

For example we now package our simple jdbc url, user, pass into jdbc.properties first, then into hibernate properties second and then into Spring beans third time!

Versus all that, consider getting a connection where you need it is really as simple as shown below in pure java, which is what we really are doing after going through all that hot air stuff with Spring:

Connection connection = DriverManager.getConnection(url, user, pass);

That is in itself self-explanatory that its a big round about and wrapping round and round to do a simple thing fast and easy with no other big benefits really. It's like wrapping tons and tons of gift paper around a tiny nice gift which is all you really keep anyway.

Another example is a batch update. With Spring it is convoluted involving quite a few classes, interfaces before you can use the JdbcTemplate to do a batch update. With plain jdbc its simply:

Statement statement = connection.createStatement();
statement.addBatch(sqlquery);
statement.executeBatch();

Can't get simpler or faster than that.

I do not support this framework. Sorry. Who on earth wants injections every time they need anything?

3
  • 6
    that code is simple, but where is your transcation handling defined and how do you test it ? Both things are made simpler by spring. Also, you java code is directly tied to a db connection, unless you store connection urls and passwords externally,this is also made simpler by spring. Commented Oct 21, 2012 at 13:18
  • +1 for this answer, to address the above comment, man use your own light weight design patterns (GOF), singleton for connection pooling, a proxy class that provides sql (string) and values (array) to the Database Object (which method, depends on http method), the dbobject handles connection pooling, transactions etc. executing query followed by release. One object use in all modules, no one needs excessive boiler plate code. bonus point with setting unit tests on proxy class and dbobject. Commented Jul 2, 2015 at 7:26
  • Check out Spring-Data-JPA though! Annotate a pojo into an entity, implement an interface and define method signatures using reasonable names, such as findHammerByWeight(), and spring implements the methods for you, giving you an injectable repository you can use in all of your other business service or controller classes.
    – mancini0
    Commented Apr 5, 2017 at 2:14
15

What does the Spring framework do?

Spring is as today not only, what was known as a simple framework, it is a complete ecosystem.

Topics covered by the spring ecosystem:

  • Spring Framework (e.g. Dependency Injection, AOP ...)

  • Spring Cloud

  • Spring Data

  • Spring Security

  • Spring Batch

  • Spring Social

See here for full coverage of the ecosystem. It is possible to cherry-pick projects, so that you could use Google Guice for DI and e.g. Spring Security to handle security related things. YOu do not have to buy into the whole ecosystem.

The Spring-framework itself covers today mainly

  • Dependency Injection

  • Aspect-Oriented Programming including Spring's declarative transaction management

  • Spring MVC web application and RESTful web service framework

  • Foundational support for JDBC, JPA, JMS

Source spring.io

In general, you could say, that Spring is a collection of implemented Patterns and Practices in code, which could help to improve or speedup your application development cycle.

For what it (the core-framework) is most known for is it's capabilities in the field of dependency injection. Spring itself has, what is called Inversion of control container or short IoC Container or even shorter the container (for which "spring" is sometimes used synonymous).

What is dependency injection?

Dependency injection means, that your object receives every dependency to other objects via an externalized mechanism.

Say, you have a car, the typical way, it is implemented is:

public class Car {

    Engine e;

    public Car() { 
        e = new Engine(); 
    }

}

The car object is dependent on an engine. Since the engine is implemented as a member of car, it can not be swapped out for e.g. a test engine.

Now dependency injection comes into play:

public class Car {

    Engine e;

    public Car(Engine e) { 
        this.e = e; 
    }

}

After that, you are able to switch engines. What you see above is called constructor injection. There are other types like e.g. setter-injection or method-injection. How does Spring help you with this? Spring allows it to mark components to be injected with the annotation @Autowired and does the wiring of the injecteed object automatically - it is likely, that the component you want to inject has itself dependencies. Injectables - so to say - are marked via @Component

public class Car {

    Engine e;

    @Autowired
    public Car(Engine e) { 
        this.e = e; 
    }

}

But that is only one of the many features Spring has to offer.

Should I use Spring? Why or why not?

Since Spring is not very intrusive and offers many aids you should consider using spring. Especially for new projects, Spring Boot is very attractive. start.spring.io offers a easy to use point'n'click-interface to generate a project template to get started. It is even possible to use curl to retrieve a template:

curl start.spring.io

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/

:: Spring Initializr ::  https://start.spring.io

This service generates quickstart projects that can be easily customized.
Possible customizations include a project's dependencies, Java version, and
build system or build structure. See below for further details.

The services uses a HAL based hypermedia format to expose a set of resources
to interact with. If you access this root resource requesting application/json
as media type the response will contain the following links:
+-----------------+-----------------------------------------+
| Rel             | Description                             |
+-----------------+-----------------------------------------+
| gradle-build    | Generate a Gradle build file            |
| gradle-project  | Generate a Gradle based project archive |
| maven-build     | Generate a Maven pom.xml                |
| maven-project * | Generate a Maven based project archive  |
+-----------------+-----------------------------------------+

...

On the other hand, frameworks like spark or dropwizard offer a good starting point for quick web-app creation too.

3
  • 1
    Very informative answer!
    – GOXR3PLUS
    Commented Jul 25, 2017 at 7:23
  • Agreed, very good answer. OP, I sympathize with you. I've also had several people show me Spring demos where they "simplify" code by adding an XML file and 2 layers of indirection just so they could call the constructor on a class :) You really just need to dive in or go to a really good presentation and eventually it will become clear where the benefits and drawbacks are Commented Aug 18, 2017 at 12:30
  • After 7 years of using Java I finally have an idea of what Spring does. Commented Aug 4, 2022 at 1:08
4

It's a framework written in Java with a lot of things included to make your web application functional (e.g. support for internationalization). It also provides a good way to structure your application into layers. Use it, it will save you a lot of time in the long run.

A good book to learn about Spring is: Expert Spring MVC and Web Flow

Not the answer you're looking for? Browse other questions tagged or ask your own question.