Bean Lifecycle
A bean = an object managed by the Spring IoC container (ApplicationContext).
Spring controls: creation, initialization, usage destruction
package com.example.bean_lifecycle;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import jakarta.annotation.PostConstruct;
import jakarta.annotation.PreDestroy;
public class Main {
public static void main(String[] args) {
ApplicationContext context =
new AnnotationConfigApplicationContext(AppConfig.class);
DatabaseConnection db = context.getBean(DatabaseConnection.class);
db.query();
context.close();
}
}
@Configuration
class AppConfig {
@Bean
DatabaseConnection databaseConnection() {
return new DatabaseConnection();
}
}
class DatabaseConnection {
public DatabaseConnection() {
System.out.println("1. Contructor: Bean created");
}
@PostConstruct
public void init() {
System.out.println("2. @PostConstruct: Initialization logic");
}
public void query() {
System.out.println("3. Bean is in use");
}
@PreDestroy
public void destroy() {
System.out.println("4. @PreDestroy: Cleanup logic");
}
}
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>jakarta.annotation</groupId>
<artifactId>jakarta.annotation-api</artifactId>
<version>2.1.1</version>
</dependency>
</dependencies>
Bean Scopes
Scope = how many instances of a bean exist and how long they live.
package com.example.bean_scope;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;
public class Main {
public static void main(String[] args) {
AnnotationConfigApplicationContext context =
new AnnotationConfigApplicationContext(AppConfig.class);
MyService s1 = context.getBean(MyService.class);
MyService s2 = context.getBean(MyService.class);
System.out.println(s1 == s2);
MyEvent e1 = context.getBean(MyEvent.class);
MyEvent e2 = context.getBean(MyEvent.class);
System.out.println(e1 == e2);
}
}
@Configuration
class AppConfig {
@Bean
MyService myService() {
return new MyService();
}
@Bean
@Scope("prototype")
MyEvent myEvent() {
return new MyEvent();
}
}
class MyService {}
class MyEvent {}
Bean Autowiring
Wiring = connecting beans (objects) together via dependencies.
@Configuration
class AppConfig {
@Bean
B b() {
return new B();
}
@Bean
A a(B b) {
return new A(b);
}
}
Spring can scan classes and create beans automatically with @Component.
Instead of manually passing dependencies, Spring does it automatically.
package com.example.bean_autowiring;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;
public class Main {
public static void main(String[] args) {
ApplicationContext context =
new AnnotationConfigApplicationContext(AppConfig.class);
NotificationController controller =
context.getBean(NotificationController.class);
controller.print();
}
}
@Configuration
@ComponentScan(basePackages = "com.example.bean_autowiring")
class AppConfig {
}
@Component
class MessageService {
public String getMessage() {
return "Hello from Component";
}
}
@Component
class NotificationController {
private final MessageService messageService;
public NotificationController(MessageService service) {
this.messageService = service;
}
public void print() {
System.out.println(messageService.getMessage());
}
}
Stereotype annotations
All are specialized versions of @Component:
@Component
@Service
@Repository
@Controller
Same behavior, better semantics.