Spring Framework
Jashwanth Jampala
Software Engineer @ People Tech Group | Java Full-Stack Developer | Java , Spring Boot, Microservices, Python, React, SQL, NoSQL, AWS | Open to New Opportunities
As Java developers, we constantly seek ways to write cleaner, more efficient code. The Spring Framework (stable version 5.3.32 as of March 2025) delivers just that by managing object creation and wiring through Inversion of Control (IoC) and Dependency Injection (DI). In this article, I’ll walk you through Spring’s powerful DI types—byType, byName, and byConstructor—across XML, Java-based, and annotation-driven setups, plus a deep dive into essential annotations with real-world examples. Whether you’re maintaining legacy code or building a new app, these tools will elevate your Spring game.
Here are the Spring projects I have worked on : [Github]
IoC Container: The Engine of Spring
The Inversion of Control (IoC) Container is Spring’s backbone. Instead of your code controlling object creation (e.g., using new), Spring flips the script—hence “inversion.” You define what you need, and the IoC container delivers it.
What It Does:
Example (XML):
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
Student student = context.getBean(Student.class);
Dependency Injection: Wiring Made Simple
Dependency Injection (DI) is how Spring connects beans. Rather than a Student class creating its own Mobile, Spring injects the Mobile into a Student. This reduces tight coupling and makes code easier to test and maintain.
Let’s see DI in action with its key types.
Base Classes for Examples
public class Mobile {
public void ring() { System.out.println("Ring ring!"); }
}
public class Student {
private Mobile mobile;
public void setMobile(Mobile mobile) { this.mobile = mobile; }
public Student() {}
public Student(Mobile mobile) { this.mobile = mobile; }
public void study() { mobile.ring(); System.out.println("Studying..."); }
}
DI Types Across Configurations
1. ByType: Matching by Class Type
<beans xmlns="https://www.springframework.org/schema/beans"
xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="mobile" class="com.example.Mobile" />
<bean id="student" class="com.example.Student" autowire="byType" />
</beans>
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
Student student = context.getBean(Student.class);
student.study(); // Output: Ring ring! Studying...
Java-Based:
@Configuration
public class AppConfig {
@Bean
public Mobile mobile() { return new Mobile(); }
@Bean
public Student student(Mobile mobile) { return new Student(mobile); }
}
@Component
public class Student {
@Autowired // By type
private Mobile mobile;
public void study() { mobile.ring(); System.out.println("Studying..."); }
}
@Component
public class Mobile { public void ring() { System.out.println("Ring ring!"); } }
@Configuration
@ComponentScan("com.example")
public class AppConfig { }
Run: Same output.
2.ByName: Matching by Property Name
How It Works: Spring links a bean by matching its ID to the property name.
XML:
<bean id="mobile" class="com.example.Mobile" />
<bean id="student" class="com.example.Student" autowire="byName" />
Java-Based:
@Configuration
public class AppConfig {
@Bean(name = "mobile")
public Mobile mobile() { return new Mobile(); }
@Bean
public Student student() {
Student s = new Student();
s.setMobile(mobile()); // Mimics byName
return s;
}
}
Run: Same output.
Annotation-Driven:
@Component
public class Student {
@Autowired
@Qualifier("mobile") // By name
private Mobile mobile;
public void study() { mobile.ring(); System.out.println("Studying..."); }
}
@Component("mobile")
public class Mobile { public void ring() { System.out.println("Ring ring!"); } }
<bean id="mobile" class="com.example.Mobile" />
<bean id="student" class="com.example.Student">
<constructor-arg ref="mobile" />
</bean>
Run: Same output.
Java-Based:
@Configuration
public class AppConfig {
@Bean
public Mobile mobile() { return new Mobile(); }
@Bean
public Student student(Mobile mobile) { return new Student(mobile); }
}
Annotation-Driven:
@Component
public class Student {
private final Mobile mobile;
@Autowired
public Student(Mobile mobile) { this.mobile = mobile; }
public void study() { mobile.ring(); System.out.println("Studying..."); }
}
Additional DI Modes
<bean id="mobile" class="com.example.Mobile" />
<bean id="student" class="com.example.Student">
<property name="mobile" ref="mobile" />
</bean>
Field Injection (Annotations):
@Component
public class Student {
@Autowired
private Mobile mobile;
public void study() { mobile.ring(); }
}
Method Injection (XML):
<bean id="student" class="com.example.Student">
<replaced-method name="study" replacer="replacer" />
</bean>
<bean id="replacer" class="com.example.StudyReplacer" />
Lookup Method Injection (XML):
<bean id="student" class="com.example.Student">
<lookup-method name="getMobile" bean="mobile" />
</bean>
<bean id="mobile" class="com.example.Mobile" scope="prototype" />
Key Spring Annotations: Practical Examples
Annotations streamline Spring configuration. Here’s how they work in practice:
@Service
public class StudentService {
public String getInfo() { return "Student Service Active"; }
}
@Autowired:
@Component
public class Classroom {
@Autowired
private StudentService service;
public void start() { System.out.println(service.getInfo()); }
}
@Qualifier:
@Component
public class Classroom {
@Autowired
@Qualifier("studentService")
private StudentService service;
}
@Configuration:
@Configuration
public class AppConfig {
@Bean
public Mobile mobile() { return new Mobile(); }
}
@Bean:
@Configuration
public class AppConfig {
@Bean
public Student student() { return new Student(mobile()); }
}
@ComponentScan:
@Configuration
@ComponentScan("com.example")
public class AppConfig { }
@Value:
@Component
public class Student {
@Value("Good morning!")
private String greeting;
public void say() { System.out.println(greeting); }
}
@Scope:
@Component
@Scope("prototype")
public class Mobile { }
@Lazy:
@Component
@Lazy
public class Student {
public Student() { System.out.println("Lazy Student created"); }
}
Other Important Concepts
<bean id="student" class="com.example.Student">
<property name="mobile">
<bean class="com.example.Mobile" />
</property>
</bean>
@Component
public class Student {
@Autowired
private Mobile mobile;
}
@Component
public class Mobile {
@Autowired
private Student student;
}
Fix:
@Component
public class Student {
private final Mobile mobile;
@Autowired
public Student(@Lazy Mobile mobile) { this.mobile = mobile; }
}
Setting Up Spring with Maven
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.3.32</version>
</dependency>
</dependencies>
Software Engineer @PeopleTechGroup | Gen-AI and ML | AWS-certified AI Practitioner | Computer Science Graduate@George Washington University |
4 天前Insightful
SWE @ People Tech Group Inc
4 天前Very informative