Photo by Miltiadis Fragkidis on Unsplash
From Tight Coupling to Loose Coupling: The Spring Boot Advantage - PART 2
Introduction
As discussed in From Tight Coupling to Loose Coupling: The Spring Boot Advantage - PART 1 in this article we'll see how Spring Beans are helpful in achieving loose coupling even when you're already using Java Interfaces. Before we proceed let's try to understand what is a Spring Bean and how is it different from Plain Old Java Objects (POJO).
POJO
A POJO is a regular Java class with fields, getters, setters and some business methods. It does not follow any framework specific conventions. They're manually created, manged by developers and dependencies need to be manually set or instantiated.
Example 1 : Java POJO
public class Car{
private String name;
private String type;
// Constructor
public Car(String name, String type) {
this.name = name;
this.type= type;
}
// Getters and Setters
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getType() {
return type;
}
public void setType(int type) {
this.type= type;
}
// Any other business methods, toString(), hashCode() etc
}
Spring Beans
A Spring Bean is an object that is created, configured and managed by Spring IoC (Inversion of Control) Container. Spring manages the lifecycle: creation and destruction of a Bean.
Beans can have dependencies automatically injected by Spring, promoting loose coupling. In simple words, no need to manually instantiate dependencies using new keyword because the framework will provide you objects via Dependency Injection.
Example 2 : Spring Bean
- Define interface and its implementations in concrete classes
public interface Engine {
void start();
}
@Component
public class PetrolEngine implements Engine {
@Override
public void start() {
System.out.println("Petrol engine started.");
}
}
@Component
public class DieselEngine implements Engine {
@Override
public void start() {
System.out.println("Diesel engine started.");
}
}
- Define the dependent class
@Component
public class Car {
private final Engine engine;
@Autowired
public Car(Engine engine) {
this.engine = engine;
}
public void start() {
engine.start();
}
}
- Define Spring Configuration using Annotation @SpringBootApplication
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
OR using Java based configuration
@Configuration
public class AppConfig {
@Bean
public Engine petrolEngine() {
return new PetrolEngine();
}
@Bean
public Car car(Engine engine) {
return new Car(engine);
}
}
Still wondering what we've done in above code and what are all those Annotations with "@" being used for ? No worries, we'll be covering them briefly below and in details in upcoming articles, so stay tuned!
Spring offers various ways to configure Beans such as XML based, Annotation based and Java-based configuration.
@Component : Indicates that the class is a Spring managed Bean.
@Annotation : Used for Dependency Injection
@SpringBootApplication : It bundles several other annotations and configurations into one by enabling Spring Boot's auto configuration, allowing Spring to find and register Beans. This annotation is placed on the main class of your application.
Summary
This article explores the concepts of Spring Beans and how they facilitate loose coupling in Java applications. It discusses the creation, configuration, and management of Spring Beans by the Spring IoC Container, highlighting the benefits of dependency injection and different ways to configure Beans. Concrete examples are provided to illustrate the differences between POJOs and Spring Beans, alongside brief explanations of the key annotations used. Stay tuned for detailed coverage in subsequent articles.