
What's the Spring Framework?
The Spring Framework, or simply Spring, is one of the most popular frameworks for creating web applications in Java. A framework is like a library (perhaps you're more familiar with this term), but there is something to consider. Roughly speaking, when you use a library, you simply create instances of the classes that it contains, call the methods you need, and thus get the result you need. In other words, this is more imperative approach: in your program, you explicitly indicate the specific moment when you need to create which object, when to call which specific method, etc. With frameworks, things are slightly different. You simply write some classes of your own and write some logic in them, but then the framework itself creates instances of your classes and calls their methods. Your classes usually implement some interfaces from the framework or inherit some of its classes, thus providing you with some functionality that has already been written for you. But this isn't always the case. For example, Spring tries as much as possible to avoid such tight coupling (where your classes directly depend on classes/interfaces in the framework). It uses annotations to achieve this. We'll return to this later. But it's important to understand that Spring is just a collection of classes and interfaces that are available for you to use :) I also want to note right away that Spring can be used not only for web applications, but also for the most common console programs that are so familiar to all of us. And we'll even write one of them today.Structure
But Spring is not just one particular framework. Rather, it is a common name used to refer to several small frameworks, each of which does its own kind of work.
https://docs.spring.io/spring/docs/4.3.26.RELEASE/spring-framework-reference/htmlsingle/
Figure 2.1. Overview of the Spring Framework
- Data Access
- Web
- Core
- and more
Why does Java have the Spring Framework?
Well, besides the fact that it is fashionable, slick, and fresh, I can say right now that as soon as you get even a small amount of skill using Spring, you will understand how there are all kinds of work that you no longer have to do, and how much work Spring takes upon itself. You can write a couple dozen lines of configuration settings and write a couple of classes, and you end up with a working project. But as soon as you start wondering how much stuff is under the hood, how much work is being done, and how much code you would have to write if you were going to implement the same project based on plain servlets or sockets and pure Java, your hair will stand on end :) Spring is even described as a kind of magic. You experience this when you see that everything works, but you also have a rough idea of how and how much work is happening behind the scenes — so it seems that there really is some kind of magic in action :) It's easier to call it magic than to try to explain how it's all interconnected. :) The second argument in favor of studying Spring is that approximately 90% of job openings for junior developers (based on my personal observations) require either knowledge of or at least a general idea of what Spring'sData
, Web MVC
, and Security
modules offer sophisticated developers :)
But today is just about the basics.
DI/IoC
If you've ever tried to read about Spring, then the first thing you encountered was probably these acroynyms: DI/IoC. Now I highly recommend that you take a break from this article and read this DZone article! IoC stands for inversion of control. I already mentioned this in passing when I wrote that using a library involves you yourself indicating in your code which method to call on which object, but that using a framework generally means that the framework will call your code at the right time. In other words, in this latter case, you are no longer managing the process of executing the code/program — the framework does this for you. You passed control to the framework (inversion of control). DI stands for dependency injection. With dependency injection, you don't create cat objects in the main method and then pass them to your methods. Instead, the Spring Framework creates them for you. You simply say something like "I want to get a cat here" and the framework passes one to you in your method. We'll see this abbreviation in future articles.Beans and context
One of the key concepts in Spring is a bean. In fact, this is just a object of some class. Suppose we have a program that requires 3 objects: a cat, a dog, and a parrot. And we have a bunch of classes with a bunch of methods. Sometimes we need a cat for a method, sometimes we need a dog for a different method, and sometimes our methods need both a cat and a parrot (for example, the method for feeding the cat, ha-ha). For still other methods, all three objects are needed. Yes, we could first create these three objects in the main method, and then pass them to our classes, and then within these classes pass them to the relevant methods... And so on throughout the entire program. But if we also suppose that we occasionally want to change the list of input parameters for our methods (for example, we decide to rewrite something or add new functionality), then we will have to make quite a few changes to the code. And now imagine that we have not 3, but 300 such objects. One alternative would be to gather up all our objects in one list (List<Object>
), pass it to every method, and then get the necessary object while inside the methods. But as the program runs, what if some object is added to this list, or worse, what if one is deleted? This has the potential to break every method where we use an index to get objects from the list.
To avoid this problem, we decide to store our objects not in a list, but in a map, where the key is the object's name and the value is the object itself. This allows us to retrieve the objects we need simply by using their name, e.g. get("parrot"), and in response we get the parrot object. Or the key could be the object's class, and the value could be the object itself. In this case, rather than specifying the name of the object, but can just specific the class of the object we need. That's also convenient. Or we could even write some kind of wrapper for the map, where some methods get objects by their name, and other methods get objects by their class.
What we have arrived at here is called an application context in the Spring Framework.
A context is a collection of beans (objects). We access a context to get the bean (object) we need by its name, by its type, or by some other means.
Additionally, we can ask Spring itself to go look in its own context for the bean we need and pass it to our method.
For example, suppose we had a method like this:
public void doSomething(Cat cat) {
...
}
When Spring called this method, it took our cat object from its context and passed it to the method. But now we've decided that, in addition to a cat, our method also needs a parrot. With Spring, nothing could be easier!
We simply write:
public void doSomething(Cat cat, Parrot parrot) {
...
}
Now when Spring calls our method, it understands the need to pass a cat and a parrot, so it goes to its context, get these two objects, and passes them to our method.
By transferring the reins of control to Spring, we also transfer responsibility for creating objects and passing them to our methods, which Spring will call.
This begs the question: how does Spring know which objects (beans) to create?
Ways to configure an application
There are three main ways to configure an application, that is, ways to tell Spring exactly which objects we need:- XML configuration files
- Java-based configuration
- automatic configuration
- the method with the top priority, which should be preferred, is automatic configuration
- if automatic configuration can't be used to correctly configure all the possible beans, use Java-based configuration (which involves creating objects using Java code)
- and the lowest-priority method is the old-fashioned way — using XML config files.
GO TO FULL VERSION