A Guide to Spring Beans in Java

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.

spring

Photo by Aniket Bhattacharya on Unsplash

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.

spring beans on a tree

Photo by Nikoli Afina on Unsplash

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

Spring 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, @SessionScopeor @ApplicationScope annotations in your Java code. Since you can only have one application the application scope behaves like the singleton scope.

Photo by Stéphan Valentin on Unsplash

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

Photo by Jen Theodore on Unsplash

Spring 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 the 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

Java Spring is a beast, there is so much to learn and cover. This article tries to explain the important parts of Spring beans in Java. I started simple then drilled down into the nuances of Spring 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 on Medium for more articles or give the TypeScript, AWS, and Angular tabs a look.