In Spring, you can define and inject dependencies using annotations, which simplifies the process of configuring beans and their relationships. Here’s how you can do it step by step:
1. Define a Dependency with @Component
To define a class as a Spring-managed component (or bean), you annotate it with @Component
, which makes the class eligible for dependency injection.
package org.kodejava.spring;
import org.springframework.stereotype.Component;
@Component
public class MyDependency {
public void doSomething() {
System.out.println("Dependency logic executed.");
}
}
Here, @Component
tells Spring to manage the lifecycle of this class as a bean.
2. Inject the Dependency with @Autowired
You can inject dependencies into another class by using the @Autowired
annotation. It can be applied to:
- Field injection
- Constructor injection (recommended)
- Setter injection
A. Field Injection
package org.kodejava.spring;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class MyService {
@Autowired // Spring automatically injects the MyDependency bean here
private MyDependency myDependency;
public void performTask() {
myDependency.doSomething();
}
}
B. Constructor Injection (Recommended)
Constructor injection is preferred as it makes the dependencies immutable and facilitates better testing.
package org.kodejava.spring;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class MyService {
private final MyDependency myDependency;
@Autowired
public MyService(MyDependency myDependency) {
this.myDependency = myDependency;
}
public void performTask() {
myDependency.doSomething();
}
}
Note: From Spring 4.3 onward, if a class has only one constructor, the @Autowired
annotation is optional since Spring will automatically use that constructor to inject dependencies.
C. Setter Injection
package org.kodejava.spring;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class MyService {
private MyDependency myDependency;
@Autowired
public void setMyDependency(MyDependency myDependency) {
this.myDependency = myDependency;
}
public void performTask() {
myDependency.doSomething();
}
}
3. Marking Other Components
Instead of using @Component
, Spring provides additional stereotype annotations for specific roles, although they work similarly. These are:
@Service
: Used for service classes.@Repository
: Used for data access/DAO components.@Controller
: Used for Spring MVC controllers.
Example:
import org.springframework.stereotype.Service;
@Service
public class MyService {
public void executeService() {
System.out.println("Executing service logic...");
}
}
4. Enable Component Scanning
To ensure Spring automatically discovers and registers your components, you need to enable component scanning using the @ComponentScan
annotation in your configuration class.
Example configuration class:
package org.kodejava.spring;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan(basePackages = "org.kodejava")
public class AppConfig {
}
Alternatively, if you are using Spring Boot, component scanning is enabled automatically for classes within the same package or sub-packages of the main application class annotated with @SpringBootApplication
.
5. Example of Application Setup
Here’s a complete example:
Dependency
package org.kodejava.spring;
import org.springframework.stereotype.Component;
@Component
public class HelloWorldService {
public String sayHello() {
return "Hello, World!";
}
}
Service
package org.kodejava.spring;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class GreetingService {
private final HelloWorldService helloWorldService;
@Autowired
public GreetingService(HelloWorldService helloWorldService) {
this.helloWorldService = helloWorldService;
}
public void printGreeting() {
System.out.println(helloWorldService.sayHello());
}
}
Main Application
package org.kodejava.spring;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class Application {
public static void main(String[] args) {
ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
GreetingService greetingService = context.getBean(GreetingService.class);
greetingService.printGreeting();
}
}
Configuration
package org.kodejava.spring;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan(basePackages = "org.kodejava")
public class AppConfig {
}
Summary of Annotations:
@Component
: Marks a class as a Spring bean.@Service
: A specialization of@Component
, typically used for service-layer classes.@Repository
: A specialization of@Component
, used for DAO/repository classes.@Controller
: A specialization of@Component
, used for Spring MVC controllers.@Autowired
: Marks a dependency to be automatically injected by Spring.@ComponentScan
: Specifies the base package(s) for scanning components.
This approach makes dependency management clean and reduces boilerplate code compared to XML-based configurations.
Maven Dependencies
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>6.2.6</version>
</dependency>