Leading up to this lesson, you've been introduced to the concept of beans several times. This lesson will reiterate what you have learned so far with a formal introduction, in turn helping to ensure your understanding of what beans are and how they are used in a Spring application.
What is a Spring Framework Bean?
A Spring "bean" is any object that is being managed by the Spring IoC container.
According to the Spring Framework Docs:
In Spring, the objects that form the backbone of your application and that are managed by the Spring IoC container are called "beans". A bean is an object that is instantiated, assembled, and managed by a Spring IoC container. Otherwise, a bean is simply one of many objects in your application. Beans, and the dependencies among them, are reflected in the configuration metadata used by a container.
Why are Spring Beans Useful?
In essence, you declare "beans," which are just objects that Spring will create and manage in the IoC container, having them readily available for injection wherever you instruct Spring to do so.
You may be asking "Why is this useful??", and that is a perfectly legitimate question at this point. The short answer is that it will make your applications much more flexible and effective by loosening the ties between different classes - "de-coupling" them.
Recall that the Spring IoC container (think back to the ApplicationContext) is responsible for managing dependencies (objects). It takes charge of creating objects, establishing connections between them, and overseeing their life cycles. These objects, thoughtfully handled by the IoC container, are affectionately termed beans.
So there you have it. A Spring Framework "bean" is just a fancy way of referencing objects that are managed by the Spring IoC container. And you are already using them. Let's take a look!
Example Location:com.codingnomads.corespring.examples.springbeans
First, a simple SpringDeveloper class:
public class SpringDeveloper {
// Address is a dependency of SpringDeveloper. The SpringDeveloper
// class depends on the Address class. They are "tightly coupled".
private Address address;
// standard constructor requires an Address
public SpringDeveloper(Address address) {
this.address = address;
}
// getter , setter...
}
SpringDeveloper needs an object of type Address:
public class Address {
private String street;
private Integer streetNumber;
public Address(String street, Integer streetNumber) {
this.street = street;
this.streetNumber = streetNumber;
}
// getters, setters...
}
You could simply create these objects manually and use them somewhere:
Address address = new Address("Main Street", 1500);
SpringDeveloper springDeveloper = new SpringDeveloper(address);
Up until now, this is how you've instantiated your objects. But with Spring Framework, you can handle object creation differently. Why do it differently with Spring?
Because real-world applications generally contain hundreds or thousands of classes. That means creating dependencies and managing their life cycles manually (which will be discussed in a later section) would be an immense (and unrealistic) undertaking. There is a better way.
Leverage the power of IoC and let Spring handle the beans! You simply declare the requirements and let Spring's IoC container do the work according to your declarations/configurations.
How Does the IoC Container Manage Beans?
You probably already know the answer. Spring, acting as the orchestrator, reads your metadata instructions to construct objects and intelligently interconnects them, presenting a streamlined and efficient alternative to manual instantiation.
Remember: Spring "metadata" can be in the form of XML, Java annotations, or Java code. Using annotations such as @Bean and @Component is the most modern and common approach.
So now, modify the previous SpringDeveloper class the Spring way:
@Component
public class SpringDeveloper {
private Address address;
public SpringDeveloper(Address address) {
this.address = address;
}
}
Adding the @Component annotation instructs the IoC container to create a bean of the type SpringDeveloper. We will discuss this annotation in greater depth later.
Create a new SpringBeansDemoConfig class:
@Configuration
@ComponentScan(basePackageClasses = SpringDeveloper.class)
public class SpringBeansDemoConfig {
@Bean
public Address address() {
return new Address("Main Street", 1500);
}
}
In this configuration:
- The
@Configurationannotation prompts Spring to scan this class for one or more @Bean methods. - Adding
@Beantoaddress()signals the IoC container that we need a bean of type Address. - Consequently, when Spring creates an instance of your SpringDeveloper class, the IoC container will automatically inject the Address bean as a dependency through constructor injection.
The following annotation serves as a directive to the IoC container, instructing it to explore the SpringDeveloper class for annotated components and subsequently generate a corresponding bean:
@ComponentScan(basePackageClasses = SpringDeveloper.class)
Finally, a bootstrapping class:
public class SpringBeansDemo {
public static void main(String[] args) {
ApplicationContext ctx = new
AnnotationConfigApplicationContext(
SpringBeansDemoConfig.class);
SpringDeveloper springDeveloper =
ctx.getBean(SpringDeveloper.class);
System.out.println("Spring Developer Address: " +
springDeveloper.getAddress().getStreetNumber() + " " +
springDeveloper.getAddress().getStreet());
}
}
Running the example produces the following output:
Spring Developer Address: 1500 Main Street
This output demonstrates the basic idea here - declaring beans that Spring will create and inject where necessary, via the IoC container. This concept is used heavily in Spring applications - keep it in mind - as you'll encounter and apply it extensively in the upcoming examples and hands-on labs.
Learn by Doing
Package: com.codingnomads.corespring.examples.springbeans
- Create a new POJO and add it as a field to your SpringDeveloper class, add it to the constructor as well. This is now a dependency of your SpringDeveloper class.
- Declare a bean for this new POJO in SpringBeansDemoConfig.
- In your bootstrapping class, print the new field to demonstrate that it has been injected.
Please be sure to push your work to GitHub when you're done.
Tip: Any time you get stuck on an example, practice exercise, or Learn by Doing, make sure to note it down for discussion with your mentor - or bring it up on Discord, we are here to help!
Summary: Spring Framework Beans
- Spring Framework Beans are objects that are created and managed by the Spring IoC container.
- Spring will inject beans wherever you tell it to do so.