Spring Boot HandBook

    Introduction to Spring beans#

    In the Spring Framework, a Bean is a fundamental concept that represents an object managed by the Spring IoC (Inversion of Control) container. These beans are the backbone of any Spring application, as they encapsulate the application's core business logic, data, and services. Understanding how beans work is crucial for mastering Spring and building effective, modular, and maintainable applications.

    What is a Bean?#

    In simple terms, a bean is an object that is instantiated, configured, and managed by the Spring IoC container. Beans are the primary building blocks of a Spring application. They are defined either through XML configuration, annotations, or Java-based configuration. The container is responsible for managing the lifecycle of these beans, including their creation, configuration, and destruction.

    Key Characteristics of Beans#

    • Singleton by Default: By default, Spring beans are singleton, meaning that only one instance of a bean is created per Spring IoC container. This instance is shared across the entire application.
    • Configurable: Beans can be customized and configured through XML, annotations, or Java code.
    • Managed by the Container: The entire lifecycle of a bean—from instantiation to destruction—is managed by the Spring IoC container.

    Defining Beans in Spring#

    There are three primary ways to define beans in Spring:

    XML-Based Configuration#

    In XML-based configuration, beans are defined in an XML file (usually named applicationContext.xml). Each bean is represented by a <bean> tag, where you can specify the bean's class, properties, and dependencies.

    <bean id="myBean" class="com.example.MyClass"> <property name="propertyName" value="propertyValue"/> </bean>

    Annotation-Based Configuration#

    Spring allows you to define beans using annotations directly in your Java classes. The most common annotation for this purpose is @Component, which marks a class as a Spring bean.

    @Component public class MyClass { // Class implementation }

    To enable component scanning, which automatically detects and registers beans annotated with @Component, you need to add the @ComponentScan annotation in your configuration class.

    @Configuration @ComponentScan(basePackages = "com.example") public class AppConfig { // Configuration code }

    Java-Based Configuration#

    In Java-based configuration, beans are defined using @Bean methods inside a @Configuration class. This approach provides a type-safe way of defining beans and is often used in modern Spring applications.

    @Configuration public class AppConfig { @Bean public MyClass myBean() { return new MyClass(); } }

    Bean Scopes#

    Spring provides several scopes that determine the lifecycle of a bean:

    • Singleton: (Default) A single instance per Spring IoC container.
    • Prototype: A new instance is created each time the bean is requested.
    • Request: A new instance is created for each HTTP request. This scope is used in web applications.
    • Session: A new instance is created for each HTTP session.
    • Global Session: A new instance is created for each global HTTP session. This is typically used in portlet-based applications.
    • Application: A single instance for the entire web application lifecycle.

    You can specify the scope of a bean using the @Scope annotation or by configuring it in XML.

    @Component @Scope("prototype") public class MyClass { // Class implementation }

    Dependency Injection with Beans#

    Dependency Injection (DI) is a key feature of Spring that allows the IoC container to manage the dependencies between beans. There are several ways to inject dependencies in Spring:

    Constructor Injection#

    In constructor injection, dependencies are provided through the constructor of the bean.

    @Component public class MyClass { private final MyDependency myDependency; @Autowired public MyClass(MyDependency myDependency) { this.myDependency = myDependency; } }

    Setter Injection#

    In setter injection, dependencies are provided through setter methods.

    @Component public class MyClass { private MyDependency myDependency; @Autowired public void setMyDependency(MyDependency myDependency) { this.myDependency = myDependency; } }

    Field Injection#

    In field injection, dependencies are injected directly into the fields.

    @Component public class MyClass { @Autowired private MyDependency myDependency; }

    Bean Lifecycle#

    Understanding the lifecycle of a bean is crucial for managing resources effectively. The typical lifecycle stages of a Spring bean are:

    1. Instantiation#

    The IoC container instantiates the bean using the class's constructor.

    2. Populating Properties#

    The container injects the bean's dependencies, either through constructor injection, setter injection, or field injection.

    1. @PostConstruct Method If a bean has a method annotated with @PostConstruct, this method is called after the bean is fully initialized.
    @PostConstruct public void init() { // Initialization code }

    3. Bean Usage#

    The bean is now ready to be used by the application.

    1. @PreDestroy Method Before the bean is destroyed, the container calls the method annotated with @PreDestroy, allowing the bean to release any resources it holds.
    @PreDestroy public void cleanup() { // Cleanup code }

    4. Destruction#

    Finally, the container destroys the bean, freeing up memory.

    Now Let us see examples of Defining and using a bean using annotations.#

    Step 1 - Define the Bean#

    First, we’ll define a simple bean that represents a service for greeting users.

    @Component public class GreetingService { public String greet(String name) { return "Hello, " + name + "!"; } }

    In this example, GreetingService is a Spring bean, and it provides a method greet to generate a greeting message.

    Step 2 - Use the Bean in Another Component#

    Next, we’ll use the GreetingService bean in another class to greet a user.

    @Component public class UserController { private final GreetingService greetingService; @Autowired public UserController(GreetingService greetingService) { this.greetingService = greetingService; } public void greetUser(String name) { String message = greetingService.greet(name); System.out.println(message); } }

    In this example, the UserController class depends on GreetingService to greet a user. The @Autowired annotation tells Spring to inject the GreetingService bean into the UserController class.

    Step 3 - Configure and Run the Application#

    Finally, we’ll create a configuration class to bootstrap the Spring application.

    @Configuration @ComponentScan(basePackages = "com.example") public class AppConfig { } public class MainApplication { public static void main(String[] args) { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class); UserController userController = context.getBean(UserController.class); userController.greetUser("John"); context.close(); } }

    In this example, AppConfig is the configuration class that tells Spring to scan the com.example package for components. The MainApplication class creates an application context, retrieves the UserController bean, and calls the greetUser method.

    Similarly we can also do XML based configuration#

    Consider the same class called GreetingService that provides a method to greet users.

    Step 1 - Consider same GreetingService Class#

    public class GreetingService { private String greeting; public void setGreeting(String greeting) { this.greeting = greeting; } public String greet(String name) { return greeting + ", " + name + "!"; } }

    In this class, we have a greeting property and a greet method that uses this property to generate a greeting message.

    Step 2: Define the Bean in applicationContext.xml#

    Next, we define this GreetingService bean in an XML configuration file, typically named applicationContext.xml:

    <beans xmlns="<http://www.springframework.org/schema/beans>" xmlns:xsi="<http://www.w3.org/2001/XMLSchema-instance>" xsi:schemaLocation="<http://www.springframework.org/schema/beans> <http://www.springframework.org/schema/beans/spring-beans.xsd>"> <!-- Definition of the GreetingService bean --> <bean id="greetingService" class="com.example.GreetingService"> <!-- Set the greeting property --> <property name="greeting" value="Hello"/> </bean> </beans>

    In this XML configuration:

    • The <bean> tag is used to define a bean.
    • The id attribute gives the bean a unique identifier (greetingService).
    • The class attribute specifies the fully qualified class name of the bean (com.example.GreetingService).
    • The <property> tag sets the greeting property of the GreetingService class to "Hello".

    Step 3: Use the Bean in Your Application#

    Finally, let's write a simple application to use the GreetingService bean defined in the XML configuration:

    import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class MainApplication { public static void main(String[] args) { // Load the Spring context from the XML configuration file ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); // Retrieve the greetingService bean from the context GreetingService greetingService = (GreetingService) context.getBean("greetingService"); // Use the bean String message = greetingService.greet("John"); System.out.println(message); // Close the context ((ClassPathXmlApplicationContext) context).close(); } }

    In this MainApplication class:

    • We load the Spring application context from the applicationContext.xml file.
    • We retrieve the greetingService bean by its id (greetingService).
    • We use the greet method of the greetingService bean to generate a greeting message.
    • Finally, we print the message to the console and close the application context.

    Running the Example#

    When you run the MainApplication, the output will be:

    Hello, John!

    In this article, we explored the fundamental concept of Spring Beans in the Spring Framework. We discussed what a bean is, how it is defined, and the various ways beans can be configured—using XML, annotations, and Java-based configuration. Additionally, we covered bean scopes, dependency injection methods (constructor, setter, and field injection), and the lifecycle of a bean. We also provided practical examples for both annotation-based and XML-based bean configuration, demonstrating how Spring manages the creation, configuration, and destruction of beans within an application. Understanding these concepts is essential for building robust and maintainable Spring applications.

    Last updated on Oct 13, 2024