In short, a Spring bean is an object which Spring framework manages at runtime. A Spring bean is a basic building block of any Spring application. Most of the application logic code you write will be placed in Spring beans.
The management of a Spring bean includes:
A Spring bean is a fundamental concept of the framework. As a user of Spring, you should have a deep understanding of this core abstraction.
Keep reading and you’ll find out all you need to know about Spring beans.
Advertisement
As you already know, Spring is responsible for creating bean objects. But first, you need to tell the framework which objects it should create.
How you do this?
By providing bean definitions.
Bean definitions tell Spring which classes the framework should use as beans. But that’s not all. Bean definitions are like recipes. They also describe the properties of a bean. We’re going to discuss properties later in the article. But before we go into that, let’s focus on the bean definitions.
There are three different ways in which you can define a Spring bean:
In modern projects, you’re going to use only component annotations and bean factory methods. If it comes to the XML configuration, nowadays Spring allows it mainly for the backward compatibility.
The choice between bean definition methods is mainly dictated by access to the source code of a class that you want to use as a Spring bean.
If you own the source code, you’ll usually use the @Component annotation directly on a class.
@Component class MySpringBeanClass { //... }
At runtime, Spring finds all classes annotated with @Component or its derivatives and uses them as bean definitions. The process of finding annotated classes is called component scanning.
You probably wonder what are derivatives of @Component.
@Conpontent derivatives are Spring stereotype annotations which themselves are annotated with @Component. This fact allows us to use them in place of @Component.
The list of @Component derivatives includes:
The difference between annotations is purely informational. They allow you to easily classify beans based on their general responsibility. You can use these annotations to mark a bean class as a member of a particular application layer. Yet, if it comes to Spring, the framework treats them all as @Components.
For classes you don’t own, you have to create factory methods with the @Bean annotation in a custom bean configuration class. If you don’t want to make a class dependent on Spring, you can also use this option for classes you own.
Here is a sample configuration class with a single bean factory method:
@Configuration class MyConfigurationClass { @Bean public NotMyClass notMyClass() { return new NotMyClass(); } }
Spring uses factory methods to create actual objects at runtime. As you can see, the method simply returns a new instance of a class. If such class belongs to some external library and you can’t annotate it with @Component, creating a factory method with @Bean is the only option.
The @Configuration annotation also comes from Spring. Actually, it’s a derivative of @Component but with a special purpose. The annotation marks the class as a container of @Bean definitions. You can write multiple factory methods inside a single configuration class.
At this point, you already know how to mark a class as a Spring bean. The next step is to learn how to customize the features of a bean.
No matter which bean definition method you choose, they all allow describing the same set of bean properties. Properties give details about how Spring should create objects.
The list of Spring bean properties includes:
To simplify bean definitions, Spring provides default values for almost all of their properties. However, it’s important to know how to customize defaults. Let’s investigate Spring bean properties one by one.
When you create a bean definition, you connect it with a single concrete class in your application. This class itself is the main property of a bean.
The class property is the default identifier of a bean when Spring looks for dependencies. Does that mean you can’t have multiple bean definitions for a single class? No. It’s possible. But in that case, to avoid ambiguity, you should use another bean identifier: a name.
Spring bean name is a custom string that Spring uses to identify beans. Unlike the bean class, names must be unique across the whole application. You can’t define two beans with the same name, even if their types are different.
Fortunately, you don’t have to set name for each bean you create. Spring generates names at runtime for its internal use. Unless you want to identify beans by names, you can safely go with the default setup.
The main situation in which you need to use bean names is having several beans for the same class defined with the @Bean annotation. In this case, names allow you to identify a particular instance which you want to use as a dependency of another bean.
Use the name attribute of the @Bean annotation. Here’s an example with two beans with the same type.
@Configuration class MyConfigurationClass { @Bean(name = "myBeanClass") MyBeanClass myBeanClass() { return new MyBeanClass(); } @Bean(name = "anotherMyBeanClass") MyBeanClass anotherMyBeanClass() { return new MyBeanClass(); } }
In practice, you don’t define bean names very often. Having multiple beans for a single class is rather a rare situation. Yet, it’s good to know about the possibility to name a bean.
Objects used as beans may use other beans to execute their jobs. When Spring creates an object which defines some dependencies, the framework needs to create these dependencies first. These dependencies can also have their own dependencies.
In Object-oriented application, we usually work with a huge graph of related objects. Fortunately, we don’t have to think about how to construct this graph. We don’t have to think about the order in which objects should be created. Spring does all of that for us.
The only thing that Spring expects from you is the list of dependencies for a particular bean.
Bean dependency definition is a complex topic which deserves a separate article. Consider the following paragraphs as an introduction to the topic.
When you have a class marked with @Component and there is only one constructor, Spring uses the list of constructor parameters as a list of mandatory dependencies. By default, the framework uses constructor parameter types to provide appropriate objects.
@Component class BeanWithDependency { private final MyBeanClass beanClass; BeanWithDependency(MyBeanClass beanClass) { this.beanClass = beanClass; } }
In the past, we used the @Autowired annotation on constructors. However, since Spring 4.3 it’s not mandatory if there is only one constructor. Yet, if a bean class defines multiple constructors, you should mark one with @Autowired. This way Spring knows which constructor contains the list of bean dependencies.
By the same token, a bean factory method can define its dependencies. Spring calls the method with appropriate objects.
@Bean BeanWithDependency beanWithOptionalDependency(MyBeanClass beanClass) { return new BeanWithDependency(beanClass); }
The scope of a Spring bean defines how many instances of a particular class the framework creates at runtime. The scope also describes on what condition a new object is created.
Spring offers several scopes for your beans. The core of the framework comes with two:
Moreover, Spring comes with additional bean scopes dedicated to web applications:
The default scope for all beans is the singleton. When a bean has the singleton scope, Spring creates only one instance and shares it across the whole application. The singleton scope is a perfect choice for stateless objects. Nowadays, the vast majority of beans in our application are stateless singletons.
On the other hand, if your object contains a state, you should consider other scopes. To select the right one, you should ask yourself how long the framework should keep that state in memory. But that’s for another post.
No matter if you annotate a class directly with @Component or create a factory method with @Bean, the method is the same. Use the @Scope annotation and its string attribute to select a scope.
@Component @Scope("prototype") class MyPrototypeClass { //... }
@Bean @Scope("prototype") MyPrototypeClass myPrototypeClass() { return new MyPrototypeClass(); }
What is more, for web scopes Spring comes with additional alias annotations. You can use these annotations as a replacement for @Scope:
When your application starts, Spring eagerly creates all singleton beans at the startup. This default behavior allows us to quickly detect errors in bean definitions. On the other hand, eager bean initialization makes the startup of your application slow.
Fortunately, you can delay the creation of beans to the moment when they are actually needed. You can do this using the @Lazy annotation.
@Component @Lazy class MyLazyClass { //... }
Because the annotation is commonly misunderstood, I wrote a separate article dedicated the @Lazy annotation.
You may want to run some object initialization logic once Spring creates a new instance based on the bean definition.
If this logic doesn’t depend on the framework, you can run it in the constructor of the object. However, to make sure the logic is run after Spring initializes the object (e.g. after optional dependency injection), you should use the initialization callback.
If you define a bean using the @Component annotation, you have two options:
In both cases, Spring will run initialization callbacks for you.
What about beans defined with factory methods?
You set the initialization callback using @Bean annotation and its attribute called initMethod. The attribute expects a string with the name of an initialization method.
@Bean(initMethod = "someInitMethodName") MySpringBeanClass meBeanClass() { return new MySpringBeanClass(); }
Interestingly, the method used as an initialization callback can have private access control. Spring uses the reflection mechanism to call the method.
Similarly to the initialization callback, you can define a method which Spring should call when a bean object is destroyed. Predestroy callbacks are much less used but it’s good to be aware they exist.
Again, if you have access to the source code of a bean class, you can go with one of two options:
For factory method, you use the @Bean annotation and its destroyMethod attribute.
@Bean(name = "myBeanClass", destroyMethod = "cleanUpMethod") MySpringBeanClass meBeanClass() { return new MySpringBeanClass(); }
Spring beans don’t live in a vacuum.
When you start a Spring application, the framework firstly creates a special object called ApplicationContext. The ApplicationContext, also known as the Inversion of Control (IoC) container, is the heart of the framework.
The ApplicationContext is a container in which your bean objects exist.
The context is responsible for detecting and reading your Spring bean definitions. Once the ApplicationContext loads bean definitions, it can start creating bean objects for your application based on provided bean properties and their dependencies.
At this point, you should know all the details about Spring beans. You learned how to define beans and how to customize their properties. You also have a basic understanding of how Spring creates objects based on bean definitions you provide. If you find the article useful, consider signing up for my newsletter so I can inform you about similar posts. Would you like to read more about Spring basics? Please let me know about it in a comment.
Short answer: No.Fortunately, you can simulate them.Many programming languages like C++ or modern JavaScript have…
The JavaScript Promise is a concept that every modern self-respecting web developer should be familiar…
Have you ever wonder why singleton is the default scope for Spring beans? Why isn't…
Do you have multiple parameters annotated with @RequestParam in a request mapping method and feel…
Some teams prefer having a separate Maven build profile for each application runtime environment, like…
Have you just started learning JavaScript? Or maybe you already have some language experience but…