What is Spring bean?

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:

  • creating an object
  • providing dependencies (e.g. other beans, configuration properties)
  • intercepting object method calls to provide additional framework features
  • destroying an object

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

How to define Spring bean?

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:

  • annotating your class with the stereotype @Component annotation (or its derivatives)
  • writing a bean factory method annotated with the @Bean annotation in a custom Java configuration class
  • declaring a bean definition in an XML configuration file

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.

Spring bean as @Component

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:

  • @Service
  • @Repository
  • @Controller

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.

Using @Bean for factory methods

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.

Beans

Spring bean properties

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:

  • class
  • name
  • dependencies
  • scope
  • initialization mode
  • initialization callback
  • destruction callback

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.

Bean class

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.

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

How to name a Spring 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.

Bean dependencies

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.

How to define bean dependencies?

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);
}

Bean scope

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:

  • singleton – a single instance
  • prototype – multiple instances

Moreover, Spring comes with additional bean scopes dedicated to web applications:

  • request
  • session
  • global session
  • application

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.

How to set the scope of a Spring bean?

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:

  • @RequestScope
  • @SessionScope
  • @ApplicationScope

Bean initialization mode

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.

Bean initialization callback

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.

How to set bean initialization callback?

If you define a bean using the @Component annotation, you have two options:

  • Make the bean class implement InitializingBean. The interfaces will force you to implement the initialization method.
  • Write a custom initialization method and mark it with the javax @PostContruct annotation.

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.

Bean destruction callback

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.

How to set bean destruction callback?

Again, if you have access to the source code of a bean class, you can go with one of two options:

  • Implement the DisposableBean interface. Spring uses its only method a destruction callback.
  • Write a custom method and annotate it with @PreDestroy from the Javax API.

For factory method, you use the @Bean annotation and its destroyMethod attribute.

@Bean(name = "myBeanClass", destroyMethod = "cleanUpMethod")
MySpringBeanClass meBeanClass() {
   return new MySpringBeanClass();
}

How does Spring create objects from bean definitions?

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.

Bean container

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.

Conclusion

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.

Facebooktwittergoogle_plusredditlinkedinmail
Advertisement