Spring boot : All about beans

ยท

5 min read

In simple terms, Bean is a Java Object, which is created and managed by Spring container (also known as IOC Container).

IOC container -> contains all the beans which get created and also manage them.

How to create a Bean?

  1. @Component (Stereotype annotation)

  2. @Bean

    while using @Bean stereotype annotations are not needed , now this will use our configuration instead of auto configuration . If we still provide the Stereotype annotation along with a default constructor the custom configuration will take precedence over auto configuraiotn

How Spring boot find these Beans?

  1. Using @ComponentScan annotation, it will scan the specified package and sub-package for classes annotated with @Component, @Service etc.

  2. Through Explicit defining of bean via @Bean annotation in @Configuration class.

At what time, these beans get created

Eagerness

  • > Some Beans get created, When we start up an application.

  • > For ex: Beans with Singleton Scope are Eagerly initialized.(Default scope)

Lazy

  • \> Some Beans get created Lazily, means when they actually needed. for example when autowired

  • -> For ex: Beans with Scope like Prototype etc. are Lazily initialized.
    Or Beans with @Lazy annotation.

Life cycle of Bean

During Application Startup, Spring boot invokes IOC Container - (ApplicationContext provides the implementation of IOC container)

IOC Container, make use of Configuration and @ComponentScan to look out for the Classes for which beans need to be created

Beans are created post this step

Inject the Dependency into the Constructed Bean.

  • @Autowired, first look for a bean of the required type.

  • If bean found, Spring will inject it. Different ways of Injection:

    • Constructor Injection

    • Setter Injection

    • Field Injection

Perform any task before Bean to be used in application using @PostConstruct

Perform any task before Bean is getting destroyed using @PreDestory

Bean Scopes

  1. SINGLETON
  • Default scope

  • Only 1 instance created per IOC.

  • Eagerly initialized by IOC (means at the time of application startup, object get created)

Above we see how TestController2 re-uses the same User Bean

  1. PROTOTYPE
  • New Object is created every time

  • Its Lazily Initialized, means when object is created only when its required.

  1. REQUEST

- One object per request not like prototype which is new each time

- Lazily initialized.

Above at application startup no bean is created, when the http request in controller is called

Please notice that above for Student dependecy a second user object is never created

Example 2

ABOVE BEAN CREATION WILL FAIL , unless we use proxyMode

  1. SESSION
  • A single HTTP session encompasses many HTTP calls

  • New Object is created for each HTTP session persists throughout the session

  • Lazily initialized.

  • When user accesses any endpoint, session is created.Remains active, till it does not expires.

  1. APPLICATION
  • Singleton has 1 object/ioc , application extends it to 1 object across multiple IOC's if one applicaiton contains multiple IOC

Dynamically Initialized Beans | Value Annotation

To tackle unsatisfied dependency problem , we use the @Primary or @Qualifier method to specify which bean gets injected

but what if we don't want to hard code above and decide according to business logic?

We can remove sterotype annotations from both implementing classes and create beans via configuration

@Value : It is used to inject values from various sources like property variables or inline literals.

Above `isOnlineOrder` is defined in application.properties

Conditionally created beans

@ConditionalOnProperty :Bean is created Conditionally (mean Bean can be created or Not).

  • Above prefix value and havingValue refer to entry in application.properties

  • matchIfMissing refers to the default value

Advantages:

  1. Toggling of Feature

  2. Avoid cluttering Application context with un-necessary beans.

  3. Save Memory

  4. Reduce application Startup time

Spring boot Profiling

Spring Boot profiling is a feature that allows developers to create and manage different configurations for various environments (e.g., development, testing, production) within a Spring Boot application. By using profiles, you can easily switch between different sets of configurations without changing the codebase, ensuring that the application behaves appropriately in each environment.

Key Concepts of Spring Boot Profiling

  1. Profiles: Named sets of configuration properties that can be activated based on the environment. Common profiles include dev, test, and prod.

  2. Configuration Files: Spring Boot uses properties or YAML files to manage configurations. You can create environment-specific configuration files like application-dev.properties, application-test.properties, and application-prod.properties.

  3. Activation: Profiles can be activated through different methods, such as command-line arguments, environment variables, or within the application code.

How to Use Spring Boot Profiling

1. Creating Profile-Specific Configuration Files

You can create separate configuration files for each profile. For example:

Each file contains properties specific to the respective environment.

2. Activating Profiles

Profiles can be activated in several ways:

  • Command-Line Arguments:

      java -jar myapp.jar --spring.profiles.active=dev
    
  • Maven comand

mvn spring-boot:run -D spring-boot.run.profiles=prod

  • Changes in pom.xml

mvn spring-boot:run -Production

  • Environment Variables:

      export SPRING_PROFILES_ACTIVE=dev
    
  • Application Properties: You can specify the active profile in the application.properties file:

  • Programmatically: You can activate profiles within your application code:

      @SpringBootApplication
      public class MyApp {
          public static void main(String[] args) {
              SpringApplication app = new SpringApplication(MyApp.class);
              app.setAdditionalProfiles("dev");
              app.run(args);
          }
      }
    

3. Using Profile-Specific Beans

You can define beans that should only be available in certain profiles using the @Profile annotation:

@Configuration
public class AppConfig {

    @Bean
    @Profile("dev")
    public DataSource devDataSource() {
        // Configuration for development datasource
    }

    @Bean
    @Profile("prod")
    public DataSource prodDataSource() {
        // Configuration for production datasource
    }
}

Benefits of Spring Boot Profiling

  • Environment-Specific Configurations: Easily manage different configurations for various environments without changing the codebase.

  • Flexibility: Quickly switch between different profiles to test how the application behaves in different environments.

  • Maintainability: Keep environment-specific configurations separate, making the application easier to maintain and understand.

You have 2 Application and 1 common code base, how you will make sure that, BEAN is only created for 1 Application, not for other?

ย