Before, we discussed the Spring context: the place in the app’s memory where we add the object instances we want Spring to manage. Spring needs control over some of the objects of our app to augment them with the capabilities it provides. You have already learned multiple ways to add object instances to the Spring context. You also learned that we add these instances (beans) into the Spring context to make Spring aware of them.

In this chapter, we discuss how to access the beans, which we’ve added to the Spring context. We used the getBean() method of the context instance directly to access the beans. But in apps, we need to refer from one bean to another in a straightforward fashion—by telling Spring to provide a reference to an instance from its context where we need it. This way, we establish relationships among the beans (one bean will have a reference to another to delegate calls when it needs). As you probably already know, often in any object-oriented programming language, an object needs to delegate specific responsibilities to others when implementing their behavior, so you need to know how to establish such relationships among objects when you use Spring as a framework as well.

First, we start by implementing a relationship between two beans you’ll define in the configuration class by using the @Bean annotation. Here we discuss two ways you can establish the relationships among beans:

Then, we discuss a third approach, which is a technique supported by the IoC principle: dependency injection (DI). We’ll discuss how to use DI in Spring, applying the @Autowired annotation to implement the relationship between two beans (which is also an example of auto-wiring). You’ll use both these approaches together in real-world projects

Implementing relationships among beans defined in the configuration file

Say we have two instances in the Spring context: a parrot and a person. We’ll create and add these instances to the context. We want to make the person own the parrot. In other words, we need to link the two instances. This straightforward example helps us discuss the two approaches for linking the beans in the Spring context without adding unnecessary complexity and enables you to focus on the Spring configurations only.

So, for each of the two approaches (wiring and auto-wiring), we have two steps (figure 3.1):

  1. Add the person and parrot beans to the Spring context (as you learned in chapter 2).
  2. Establish a relationship between the person and the parrot.

Untitled

In section 3.1.1, we implement wiring, and in section 3.1.2, we implement auto-wiring for @Bean annotated methods. In the pom.xml file of the Maven project, we add the dependency for Spring context as you find it in the next code snippet:

<dependency>
   <groupId>org.springframework</groupId>
   <artifactId>spring-context</artifactId>
   <version>5.2.7.RELEASE</version>
</dependency>

We then define a class to describe the Parrot object and one to describe the Person. In the next code snippet, you find the definition of the Parrot class:

public class Parrot {

  private String name;

  // Omitted getters and setters

  @Override
  public String toString() {
    return "Parrot : " + name;
  }
}

In the next code snippet, you find the definition of the Person class:

public class Person {

  private String name;
  private Parrot parrot;

  // Omitted getters and setters
}

The following listing shows you how to define the two beans using the @Bean annotation in the configuration class.

@Configuration
public class ProjectConfig {

  @Bean
  public Parrot parrot() {
    Parrot p = new Parrot();
    p.setName("Koko");
    return p;
  }

  @Bean
  public Person person() {
    Person p = new Person();
    p.setName("Ella");
    return p;
  }
}