A Quick Guide to Spring Beans
Java beans? Nah Spring beans
What is Spring?
Spring is a lightweight framework for Java often used in, but not limited to, enterprise development. Spring is modular, meaning you only need to pull in the packages you use. Spring has several groups of modules Core, Web, Data Access, and Miscellaneous. Spring enables inversion of control(IoC) by using dependency injection(DI), this decouples the code and makes testing easier. The ease of DI is often seen as the biggest benefit of using Spring. Spring has some framework-specific terms, one of the most common terms used is a bean.
What is a Spring Bean?
Containers
Before learning about beans let’s look at the containers that use them. The Spring container takes a Java class and some configuration metadata and creates an application. Components passed to the container are Spring Beans. The metadata provided to the container can get set in three different ways: XML, annotations, and Java. Annotations are the ones I see most in my enterprise work environment. There are two types of containers in Spring: BeanFactory
and ApplicationContext
. Bean factory is an older lightweight container that provides backward compatibility. The ApplicationContext
container has all the functionality of BeanFactory and more, making it preferred.
What is a Spring Bean?
A Spring Bean is an object instantiated, assembled, and managed by a Spring container and created with the configuration metadata passed to that container. https://www.tutorialspoint.com/spring/spring_bean_definition.htm
This definition feels a little too technical and vague for me. I prefer a definition given by Elias Dorneles in this Stack Overflow post.
Spring beans are just instance objects that are managed by the Spring container, namely, they are created and wired by the framework and put into a “bag of objects” (the container) from where you can get them later.
The Spring documentation also has a good definition of beans. Describing them as a recipe for creating instances of the class defined by that bean definition. It’s important not to confuse Spring beans with Javabeans. Oracle defines Javabeans as a POJO that implements the serialization interface.
Bean Deep Dive
Now that we know the basics of a bean and the Spring container let's take a deeper look at the anatomy of a bean.
Bean Scope
Bean scope is a way to control the extent of the bean. When defining beans you can choose six options of bean scope. Four of these bean scopes require the use of the web-aware ApplicationContext
container, as they make use of HTTP, sockets, and servlets to determine the bean scope. The six scopes are Singleton, Prototype, Request, Session, Application, and WebSocket(the last 4 are web-aware dependent).
Singleton is the default scope of a bean. The Spring container will create one instance of your bean and cache it. Any future requests to the bean will return the cached object. This differs from the singleton design pattern. The Gang of Four singleton pattern ensures that an object is only created once in a classloader. Spring scopes the singleton to the container. An XML metadata example of setting this is below.
<bean id="badassService" class="com.foo.bar" scope="singleton"/>
Prototype scope will create a new instance of a bean every time there is a request for the bean. The general practice is to use singletons for stateless and prototype for stateful. Spring will not clean up beans with prototype scope, the developer must handle clean up.
<bean id="badassService" class="com.foo.bar" scope="prototype"/>
One note about using singleton and prototype beans together. When you have a singleton bean with a dependency on a prototype bean the prototype is instantiated then injected into the singleton. The prototype that was instantiated will be the only instance that is ever passed to the singleton bean.
Request, Session, and Application scope will create a new bean for each HTTP request/session/web app. When the single request/session/web app finishes processing the instance is destroyed. You can code this in the XML, the same way as the code examples shown above, or use the @RequestScope
, @SessionScope
or @ApplicationScope
annotations in your Java code. Since you can only have one application the application scope behaves like the singleton scope.
Bean Life Cycle
There are three ways to handle the setup and tear down of a bean: annotations, specifying an init function in the XML or implementing Spring interfaces. Of the three methods, using annotations or XML is the best practice. Using annotations allows you to decouple your code from having to implement Spring interfaces.
Beans have a single interface for setup and teardown. To set up, implement the InitializingBean
interface afterPropertiesSet()
method. For teardown, implement the DisposibleBean
destroy()
method. The recommended way to do this is to use the @PostConstruct
and @PreDestroy
annotations. Calls to methods carrying these annotations occur at the same point in the life cycle as afterPropertiesSet()
and destroy()
.
Initalization and Destroy using XMLXML:
<bean id="badassService" class="com.foo.bar" scope="prototype"
init-method="intialize" destroy-method="clean"/>Java:
public class Bar{
public void intialize(){
//This is my init method
}
public void clean(){
//this is my destroy method
}
}
The example above shows using init-method
and destroy-method
on a single bean but if you find yourself using the same methods on several Java classes you can specify default-init-method
and default-destroy-method
one level up on the beans
XML field. If you have a bean that doesn’t match your default method name that bean can use the init-method
to override the default-init-method
.
<beans default-init-method="intialize">
<bean id="badassService" class="com.foo.bar"></bean>
</beans>
If a bean has multiple configurations for a life cycle the order is as follows: annotations, Spring interface initialization, then custom initialization functions.
Bean Inheritance
When using XML child beans can inherit from parent beans using the parent
attribute. Child beans will use the class from the parent if there is no other configuration specified. Child beans will inherit scope, constructor arguments, property values, and method overrides of the parent. Any scope, initialization method, destroy method or static factory methods specified in the child bean will override the parent bean settings. Depends on, auto-wire, dependency check, singleton, and lazy init settings will always come from the parent bean.
<bean id="badassParentService" class="com.foo.bar"></bean>
<bean id="badassChildService" class="com.foo.childBar" parent="badassParentService"></bean>
Conclusion
Spring is a beast, there is so much to learn and cover. This article tries to explain the important parts of Spring beans. I started simple then drilled down into the nuances of beans as the article progresses. If any part of this article doesn’t make sense I would recommend going back up the article to the last part that did and rereading from there. The Spring documentation is always a great place to go to learn more and as always Stack Overflow has a plethora of Spring questions and answers. If you’re looking for more reads check out my profile for articles on Git, TypeScript, and AWS.