How to create Spring Beans and Inject Beans? Spring Core (2023)

How to create Spring Beans and Inject Beans? Spring Core (1)

Just imagine your favorite dish, it takes how many ingredients to pull together a dish which waters your mouth. These ingredients compliment or just say work in collaboration with each other to develop that exquisite taste. Now imagine what your favorite dish would be like had one of the ingredients is missing or added inappropriately.

In this respect, a great piece of software isn’t much different. Any non-trivial Java application is made up of several objects that must work together to meet some business goals. These objects must be aware of one another and communicate with one another to get their jobs done. These object which we are talking about, act as a backbone of our application is called Bean or JavaBeans in Spring lingo. We will be referring these objects as beans in future posts interchangeably.

In our previous post, we learned that beans shouldn’t be responsible for finding or creating other dependent beans to do their jobs. Instead, the container should give them a reference to their dependency. We also learned that the act of creating this association is called wiring.

As mentioned earlier, the Spring container is responsible for creating and managing relationships between beans via DI. But it’s your responsibility to tell spring container which beans to create and how to wire them. There are different ways to do that:

  • Automatic bean discovery and wiring
  • Explicit configuration in XMLs
  • Explicit configuration in Java

I’d favor the type-safe and more powerful JavaConfig over XML but it’s more of a personal choice. You can also mix JavaConfig and XML based upon your use-case.

Spring can configure automatic wiring by two angles:

(Video) Spring ultimate basics: What are Spring Beans and what is the Spring Container?

  • Component Scanning: Spring automatically discovers beans to be created in the application context.
  • Autowiring: Spring automatically discovers beans and satisfies dependencies.

To demonstrate the above two concepts we will be creating a few beans and wire them together.

1.1 Creating Discoverable Beans

In our previous post, we saw how Class Student should be injected with Interface Subject in order to function.

package com.lifeinhurry.person;
public Interface Subject{
public void attend();
}
package com.lifeinurry.person;
import org.springframework.stereotype.Component;
@Component
public class History implements Subject{
private String content = "history chapter";
@Override
public void attend(){
System.out.print("Reading :" + content);
}
}

The important thing to note above is that we have defined Subject as an Interface so that it can keep coupling between the implementation of Subject and the Student itself minimum. What you should also take note that we have annotated class History with @Component. This annotation identifies this class as a component class and serves as a clue to Spring that a bean should be created for this class.

However, Component scanning isn’t turned on by default. You’ll write an explicit configuration to tell Spring to check if our classes are annotated with @Component and create beans for them. Let us see how to write such a configuration.

package com.lifeinhurry;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan(basePackages="com.lifeinhurry")
public class StudentConfig{
}

Class StudentConfig defines a Spring wiring specification, expressed in Java. We’ll learn more about Java-based spring configuration in further posts. But for now, observe that StudentConfig doesn’t explicitly define any beans itself. Instead, it’s annotated with @ComponentScan to enable component scanning in Spring. This will enable Spring to scan all components in com.lifeinhurry package and it’s sub-packages (You can also configure multiple packages in ComponentScan). Spring will find class History with @Component annotation and will automatically create a bean in a Spring container.

Let us see if component scanning really works or not with the help of Junit test, that will create a Spring application context and test if Subject bean is actually created or not.

package com.lifeinhurry;
import static org.junit.Assert.*;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes=StudentConfig.class)
public class StudentTest{
@Autowired
private Subject subject;
@Test
public void subjectShouldNotBeNull() {
assertNotNull(subject);
}
}

StudentTest takes advantage of spring’s SpringJUnit4ClassRunner to have a spring application context automatically created when the test starts. And the @ContextConfiguration annotation tells it, to load configuration from the class StudentConfig. Because that configuration class includes ComponentScan, the resulting application context should include the Subject bean.

We learned how we can create a standalone bean in the Spring application context. But we know, many objects lean on other objects to get the job done. We need a way to wire our component-scanned beans with any dependency they have. To do that, we will look at autowiring further.

1.2 Annotating Beans for Autowiring

Spring automatically let beans to find their dependency within the application context, it is called autowiring. For autowiring to be enabled we need to use @Autowired annotation. To illustrate this, we will look at class Student, how it can be wired with bean of type Subject.

(Video) Spring Core: 5000 ways to build and wire your Spring Beans | Spring Core - Masterclass

package com.lifeinhurry.person;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class Student implements Person{
private Subject subject;
@Autowired
public Student (Subject subject) {
this.subject= subject;
}
public void attendSubject() {
subject.attend();
}
}

Spring has already created a Subject bean in its container using @ComponetScan feature which we saw earlier. In the above example, Spring passes the bean to class Student via the constructor. Since the constructor is annotated with @Autowired it let Spring know that it has a dependency on a bean of type Subject to perform its job. It becomes the responsibility of Spring to find and satisfies Student dependency.

The @Autowired annotation’s use isn’t limited to constructors. It can be used in multiple ways:

//Option1: Can be used with setters
@Autowired
public void setSubject(Subject subject) {
this.subject= subject;
}
//Option2: Can be used with any method
@Autowired
public void assignSubject(Subject subject) {
this.subject= subject;
}
//Option3: Can be used directly with variable
@Autowired
private Subject subject;

Now, we can be assured that the Spring will automatically inject Student with its dependency. To be more certain, let us verify it by modifying StudentTest to attend class through Student bean.

package com.lifeinhurry;
import static org.junit.Assert.*;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes=StudentConfig.class)
public class StudentTest{
@Autowired
private Subject subject;
@Rule
public final StandardOutputStreamLog log = new StandardOutputStreamLog();
@Autowired
private Student student;
@Test
public void subjectShouldNotBeNull()
{
assertNotNull(subject);
}
@Test
public void testAttendSubject()
{
assertEquals(
"Reading :history chapter",
log.getlog());
}
}

Now, we will be focusing on how we can create beans using Java configurations.

While building a Java application, you often use some third-party libraries to perform some functions. In a project, you may require to create a bean of a class that belongs to the library. So naturally, you won’t be able to annotate the class with Component or Autowired because you don’t have the source code for that library. This is the time when the automatic configuration isn’t an option and you must turn to explicit configurations.

So we will be learning how to do these explicit configurations in Java now. I prefer JavaConfig because it’s more powerful, type-safe, readable and refactor-friendly. It’s just like any other Java code in your application.

Even though these explicit configurations are Java code, we must understand that it is configuration code and set it apart from our business logic in an application. We should not add configuration in between our business logic and vice-versa. It’s often a best practice to keep JavaConfig in a separate package.

Now, let us see how we can configure Spring using JavaConfig.

Previously, we created a configuration StudentConfig where we rely on component scanning using @ComponentScan so that Spring creates a bean of a class annotated with @Component. Let us revisit StudentConfig . We will be removing @ComponentScan annotation from the config class in this case.

(Video) Spring Beans einfach erklärt

package com.lifeinhurry;
import org.springframework.context.annotation.Configuration;
@Configuration
public class StudentConfig{
}

If you see the above code snippet, we annotated the class using just @Configuration . This annotation identifies it as a configuration class, where we will be configuring the details of the beans, that are needed to be created in Spring container.

Now In order to create a bean, we need to write a method that will be annotated with @Bean and return the object of the desired class. It will instruct Spring that any object returned by this method should be registered as a bean in Spring container. Let us understand it with the help of an example.

In our previous post, we looked at an interface Subject and class History . We will remove @Component from class History to illustrate how we can create its bean explicitly.

package com.lifeinhurry.person;
public Interface Subject{
public void attend();
}
package com.lifeinurry.person;
public class History implements Subject{
private String content = "history chapter";
@Override
public void attend(){
System.out.print("Reading :" + content);
}
}

So now History is a plain vanilla class which implements Subject interface and override its function. Let us see how we can create a bean of this class in a Spring container.

package com.lifeinhurry;
import org.springframework.context.annotation.Configuration;
@Configuration
public class StudentConfig{
@Bean
public Subject history(){
return new History();
}
}

In the above code snippet, @Bean annotation indicates that the method will return an instance of a type Subject and Spring will register it as a bean in its container/application context. By default, the bean will be represented by the method’s name. However, we can also rename the bean using name attribute below:

package com.lifeinhurry;
import org.springframework.context.annotation.Configuration;
@Configuration
public class StudentConfig{
@Bean(name="customName")
public Subject history(){
return new History();
}
}

We created a bean of the type Subject above. Now we will learn how we can wire this bean into a class Student that depends on it using JavaConfig. The simplest way to do that is to simply call the referenced bean’s method:

package com.lifeinhurry.person;
public class Student implements Person{
private Subject subject;
public Student (Subject subject) {
this.subject= subject;
}
public void attendSubject() {
subject.attend();
}
}
package com.lifeinhurry;
import org.springframework.context.annotation.Configuration;
@Configuration
public class StudentConfig{
@Bean
public Subject history(){
return new History();
}
@Bean
public Student student(){
return new Student(history());
}
}

If you notice, student() is annotated with @Bean which means it will also be registered as a bean in Spring container and its ID will be student , same as the method’s name. In the above example, when we call history() inside student() , Spring will ensure that it finds the bean in its container and wire it to an instance of the class Student .

There are other methods to wire components together as well. Let us see that.

package com.lifeinhurry;
import org.springframework.context.annotation.Configuration;
@Configuration
public class StudentConfig{
@Bean
public Subject history(){
return new History();
}
@Bean
public Student student(Subject subject){
return new Student(subject);
}
}

In the above example, student() method just takes subject as a parameter. When method student() is invoked by Spring to create its bean, it autowires the subject based on the type and satisfies its dependency. Let us verify it using the JUnit test.

(Video) What are Spring Beans @Bean & @Autowired Annotations Spring Framework #springframework #spring #java

package com.lifeinhurry;
import static org.junit.Assert.*;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes=StudentConfig.class)
public class StudentTest{
@Autowired
private Subject subject;
@Rule
public final StandardOutputStreamLog log = new StandardOutputStreamLog();
@Autowired
private Student student;
@Test
public void subjectShouldNotBeNull()
{
assertNotNull(subject);
}
@Test
public void testAttendSubject()
{
assertEquals(
"Reading :history chapter",
log.getlog());
}
}

The above test passes with flying colors.

I hope by now you are clear with the concept of different ways to define beans in a spring container and how to wire them. We discussed 2 types of configurations until now. In an enterprise-level Java application, there are many components that are working in coordination to satisfy a common goal. There are a lot of aspects involved while designing such an application and you may require to use both automatic and explicit configuration depending upon the need. Fortunately, none of the configuration options available in Spring are mutually exclusive. You’re free to mix component scanning and autowiring with JavaConfig and/or XML configuration. In Spring it doesn’t matter how the beans are being wired together until and unless it exists in a spring container. Let us understand this with the help of an example.

Above we saw both Student as well as Subject are defined in a single configuration class. What if we want both entities config to be separate.

package com.lifeinhurry;
import org.springframework.context.annotation.Configuration;
@Configuration
public class SubjectConfig{
@Bean
public Subject history(){
return new History();
}
}
package com.lifeinhurry;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
@Configuration
@Import(SubjectConfig.class)
public class StudentConfig{
@Bean
public Student student(Subject subject){
return new Student(subject);
}
}

In the above code snippet, we see that we separated the two configs. But we need a way to bring these two configuration classes together. We imported SubjectConfig into StudentConfig using @Import annotation.

Read: @Primary and @Qualifier Annotation in Spring

So by now, we learned that Spring container/application-context is the core of a Spring Framework. Spring manages the lifecycle of a bean in a container, creating beans and wiring them together so they can do their job in an application. We also learned different ways to configure and wire beans together.

I will highly recommend you to keep following the series for more topics on Spring Framework.

I hope I am able to clear the basic concepts of spring core by now. In case of any queries or doubts please feel free to drop a comment and I will get back to you as soon as possible.

Videos

1. Spring Core Annotation | Configuration, Bean
(Telusko)
2. What are spring beans? | Spring Tutorial | Spring basics | Spring Framework
(Ram N Java)
3. How to use xml configuration to manage spring beans (Java - Spring)
(Hamza)
4. Creating Spring Beans
(Spring Framework Guru)
5. Spring Component Vs Bean | Dependency Injection | Spring Tutorial |Ch1|E2|
(STUDevLantern)
6. Spring Core Tutorial 7 | Bean Property
(Telusko)
Top Articles
Latest Posts
Article information

Author: Terence Hammes MD

Last Updated: 05/05/2023

Views: 5963

Rating: 4.9 / 5 (49 voted)

Reviews: 80% of readers found this page helpful

Author information

Name: Terence Hammes MD

Birthday: 1992-04-11

Address: Suite 408 9446 Mercy Mews, West Roxie, CT 04904

Phone: +50312511349175

Job: Product Consulting Liaison

Hobby: Jogging, Motor sports, Nordic skating, Jigsaw puzzles, Bird watching, Nordic skating, Sculpting

Introduction: My name is Terence Hammes MD, I am a inexpensive, energetic, jolly, faithful, cheerful, proud, rich person who loves writing and wants to share my knowledge and understanding with you.