1. A quick refresher on Spring Beans
Spring Bean is basically an object managed by the Spring IoC container. These objects are created, initialized, configured, and eventually destroyed by the container based on your app configuration. If you want your Java object to be part of Spring's magic, it needs to be registered as a Bean.
Imagine a warehouse manager who always knows where the tool (or object) you need is stored. The IoC container is that manager, and the tools on the shelves are our beans.
How are beans registered in Spring?
There are several ways to register beans:
- Annotations (for example,
@Component,@Service,@Repository). - Java-based configuration using
@Configurationand@Bean. - XML configuration (yeah, it's still around, but it's used less and less — why bother when you have Java annotations?).
That's why Spring is flexible — pick the registration style that works for you.
2. Spring Bean lifecycle
Beans, like living things, have a lifecycle. Their life path includes creation, initialization, usage, and destruction — all controlled by the IoC container. Let's break down how this works.
Main stages of the lifecycle
- Creation: the bean is created by the IoC container.
- Initialization: the bean can set up its internal state at this point.
- Usage: the bean starts doing its job (for example, handling requests).
- Destruction: once the bean is no longer needed, the container destroys it (unless, of course, it's a singleton).
Lifecycle visualization
1. Object creation
↓
2. Dependency injection (DI)
↓
3. Call initialization methods (@PostConstruct)
↓
4. Using the bean
↓
5. Cleanup resources (@PreDestroy)
Now let's look at a concrete example.
3. How does Spring manage the lifecycle?
Spring gives us convenient annotations for that. Let's meet the key ones.
Annotations @PostConstruct and @PreDestroy
@PostConstruct: runs actions after the bean is created and all dependencies are set (for example, connects a service or loads data).@PreDestroy: fires before the bean is destroyed. Use it to free resources (like closing connections).
Example:
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
@Component
public class LifecycleDemoBean {
@PostConstruct
public void init() {
System.out.println("Bean initialized!");
}
public void doSomething() {
System.out.println("Bean is working!");
}
@PreDestroy
public void cleanup() {
System.out.println("Bean destroyed!");
}
}
When Spring sees @PostConstruct and @PreDestroy, it ensures those methods are called at the right times.
Alternative with InitializingBean and DisposableBean interfaces
If you prefer interfaces over annotations (for a more explicit contract), you can use:
InitializingBean— theafterPropertiesSet()method is called after the bean is created.DisposableBean— thedestroy()method is called before the bean is destroyed.
Example:
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.stereotype.Component;
@Component
public class AlternativeLifecycleBean implements InitializingBean, DisposableBean {
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("Object configured (InitializingBean)!");
}
@Override
public void destroy() throws Exception {
System.out.println("Object destroyed (DisposableBean)!");
}
}
While this approach works, modern projects usually prefer @PostConstruct and @PreDestroy for their simplicity and readability.
4. Managing beans with annotations
@Component and company**
@Component: a general-purpose annotation for any bean, used when a more specialized annotation doesn't fit.@Service: for classes with business logic.@Repository: for classes responsible for data access.@Controller: for MVC controllers.
Example using @Component:
@Component
public class SimpleBean {
public void sayHello() {
System.out.println("Hello, bean world!");
}
}
@Autowired and automatic dependency injection
We've touched on dependency injection a bit already, but let's go deeper.
@Autowired: lets Spring wire dependencies automatically.
Example using @Autowired:
@Component
public class DependencyBean {
public String getDependencyInfo() {
return "Dependency info.";
}
}
@Component
public class AutowiredBean {
private final DependencyBean dependency;
@Autowired
public AutowiredBean(DependencyBean dependency) {
this.dependency = dependency;
}
public void printDependencyInfo() {
System.out.println(dependency.getDependencyInfo());
}
}
When the app runs, Spring will find DependencyBean and pass it into AutowiredBean.
5. Bean scopes
By default all beans in Spring have the singleton scope. That means there's only one instance of the bean in the IoC container. But sometimes we need different scopes.
Main scopes
- Singleton: one bean per IoC container.
- Prototype: a new object is created each time the bean is requested.
- Request: one instance per HTTP request.
- Session: one instance per HTTP session.
Setting the scope
The @Scope annotation lets you control the bean's lifecycle.
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
@Component
@Scope("prototype")
public class PrototypeBean {
public PrototypeBean() {
System.out.println("A new PrototypeBean instance has been created!");
}
}
Each time this bean is requested, a new instance is created.
6. Common mistakes and how to fix them
- Missing dependency error: if you use
@Autowiredbut the bean isn't registered, Spring will throwNoSuchBeanDefinitionException. Fix? Make sure the bean is registered via annotation or configuration. - Destroying prototype beans: Spring doesn't manage the lifecycle of
prototypebeans, so you have to destroy them yourself. - Multiple matching beans: if you have several beans of the same type, Spring can get confused. Use
@Qualifierto specify the exact bean.
Example with @Qualifier:
@Component("catBean")
public class Cat {}
@Component("dogBean")
public class Dog {}
@Component
public class AnimalShelter {
@Autowired
@Qualifier("catBean") // Specify which bean to use
private Cat pet;
}
Where do we learn all this?
If you want to go deeper, here are a couple of useful links:
Long live beans, the lifecycle, and making our lives easier! Next step — even more Spring magic!
GO TO FULL VERSION