1. Core Responsibilities
The Spring framework fundamentally addresses two key concerns: object instantiation and object lifecycle management.
Object Instantiation:
Spring automatically creates instances of controllers, services, and repository classes.
Object Management:
Spring maintains references to created objects, effectively "managing" them within what is commonly called the Spring container.
When a method needs to invoke a controller, service, or repository, Spring allocates the appropriate pre-created instance. This is achieved by declaring the required object and applying the
@Autowiredannotation for automatic injection before calling any methods.
2. Object Creation Strategies
2.1 Component Scanning
Components:
Functional building blocks within a project that provide specific capabilities and can produce observable effects or data modifications.
VALID:
@Controller,@Service,@Repository, configuration classesINVALID: Entity classes, POJOs, DTOs, VO classes
Four interchangeable annotations mark classes as components for Spring's component sacnning mechanism. While functionally equivalent, each annotation conveys specific semantic meaning:
// Component annotation variants
@Component
@Controller
@Service
@Repository
// Spring MVC specific annotations
@RestController
@ControllerAdvice
@RestControllerAdvice
Spring Bean Naming:
When using component scanning, each object becomes a Spring Bean with an automatically derived name following these rules:
(1) If the class name's first letter is uppercase and second letter is lowercase, the Bean name converts only the first letter to lowercase. For instance,
ProductControllerbecomesproductController.(2) If the first two letters don't match the above pattern, the Bean name matches the class name exactly.
Custom names can be specified:
@Component("customBeanName")
Component Scanning:
Apply
@ComponentScanto a configuration class to enable scanning within a specified package hierarchy:@Configuration @ComponentScan("com.example.application") public class ApplicationConfig { }Spring scans the designated package and all subpackages, automatically instantiating any annotated components and storing them in the container.
CGLib Proxy:
CGLib (Code Generation Library) generates subclasses at runtime in memory to extend target object functionality. Spring includes this library by default.
2.2 @Bean Factory Methods
Define custom object creation logic within configuration classes using @Bean annotations:
@Configuraton
public class ServiceConfiguration {
@Bean
public OrderService orderService() {
return new OrderService();
}
}
2.3 Strategy Selection
| Type | Recommended Approach |
|---|---|
| Custom classes (your own code) | Component scanning |
| Third-party or non-scannable classes | @Bean factory methods |
3. Bean Scope Configuration
By default, Spring-managed beans operate as singletons—at most one instance exists per application lifecycle.
Note: Spring doesn't implement the Gang of Four Singleton pattern; rather, managed beans share the singleton characteristic.
Modify scope using @Scope("prototype") on classes or @Bean methods (rarely needed):
@Scope("prototype")
@Controller
public class TempReportGenerator {
}
Eager Initialization:
Singleton beans initialize immediately when the Spring context loads, analogous to the eager initialization pattern:
public class DatabaseConnection {
private static final DatabaseConnection instance = new DatabaseConnection();
private DatabaseConnection() {}
public static DatabaseConnection getInstance() {
return instance;
}
}
Lazy Initialization:
Override default behavior with @Lazy to defer creation until first access:
public class CacheManager {
private static volatile CacheManager instance;
private static final Object monitor = new Object();
private CacheManager() {}
public static CacheManager getInstance() {
if (instance == null) {
synchronized (monitor) {
if (instance == null) {
instance = new CacheManager();
}
}
}
return instance;
}
}
Key Differences:
Eager initialization creates the instance immediately
Lazy initialization defers creation until first access
4. Dependency Injection
Spring performs automatic dependency resolution when:
- A managed bean's property requires a value
- An automatically invoked method's parameters need values
Matching Criteria: Type and optionally name correspondence
Automatically Invoked Methods:
- Constructor parameters
@Beanfactory method parameters- Methods annotated with
@Autowired(typically setters)
Basic Injection Example:
@RestController
public class InvoiceController {
@Autowired
private PaymentGateway paymentGateway;
}
5. Autowiring Resolution Algorithm
Spring locates matching beans using this hierarchy:
No Matching Beans:
required=true(default): ThrowsNoSuchBeanDefinitionExceptionduring context initializationrequired=false: Field remainsnull, no exception
Single Matching Bean:
- Direct successful injection
Multiple Matching Beans:
- Attempts name-based matching as secondary filter
- If name match exists: Successful injection
- If no name match: Throws
NoUniqueBeanDefinitionException
Disambiguation:
Use @Qualifier to explicitly specify the target Bean name:
@RestController
public class NotificationController {
@Autowired
@Qualifier("emailSender")
private MessageService messageService;
}
Alternatively, use @Primary on a bean to establish default preference:
@Configuration
public class ServiceConfig {
@Bean
@Primary
public TaxCalculator standardTaxCalculator() {
return new StandardTaxCalculator();
}
@Bean
public TaxCalculator premiumTaxCalculator() {
return new PremiumTaxCalculator();
}
}