0
# Core Container & Dependency Injection
1
2
The Spring Core Container is the foundation of the Spring Framework, providing the Inversion of Control (IoC) container and dependency injection capabilities. It consists of three main modules: spring-core, spring-beans, and spring-context.
3
4
## Maven Dependencies
5
6
```xml
7
<!-- Core container with application context -->
8
<dependency>
9
<groupId>org.springframework</groupId>
10
<artifactId>spring-context</artifactId>
11
<version>5.3.39</version>
12
</dependency>
13
14
<!-- For minimal IoC container only -->
15
<dependency>
16
<groupId>org.springframework</groupId>
17
<artifactId>spring-beans</artifactId>
18
<version>5.3.39</version>
19
</dependency>
20
```
21
22
## Core Imports
23
24
```java { .api }
25
// Application Context and Configuration
26
import org.springframework.context.ApplicationContext;
27
import org.springframework.context.ConfigurableApplicationContext;
28
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
29
import org.springframework.context.support.ClassPathXmlApplicationContext;
30
31
// Configuration Annotations
32
import org.springframework.context.annotation.Configuration;
33
import org.springframework.context.annotation.Bean;
34
import org.springframework.context.annotation.ComponentScan;
35
import org.springframework.context.annotation.Import;
36
37
// Dependency Injection
38
import org.springframework.beans.factory.annotation.Autowired;
39
import org.springframework.beans.factory.annotation.Qualifier;
40
import org.springframework.beans.factory.annotation.Value;
41
42
// Component Stereotypes
43
import org.springframework.stereotype.Component;
44
import org.springframework.stereotype.Service;
45
import org.springframework.stereotype.Repository;
46
47
// Bean Factory Interfaces
48
import org.springframework.beans.factory.BeanFactory;
49
import org.springframework.beans.factory.ListableBeanFactory;
50
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
51
52
// Resource and Environment
53
import org.springframework.core.io.Resource;
54
import org.springframework.core.io.ResourceLoader;
55
import org.springframework.core.env.Environment;
56
57
// Application Startup Metrics (Spring 5.3+)
58
import org.springframework.core.metrics.ApplicationStartup;
59
import org.springframework.core.metrics.StartupStep;
60
import org.springframework.core.metrics.DefaultApplicationStartup;
61
import org.springframework.core.metrics.jfr.FlightRecorderApplicationStartup;
62
63
// Reactive Type Adapters
64
import org.springframework.core.ReactiveAdapterRegistry;
65
import org.springframework.core.ReactiveAdapter;
66
import org.springframework.core.ReactiveTypeDescriptor;
67
import org.springframework.context.annotation.PropertySource;
68
```
69
70
## Core Container Architecture
71
72
### Spring Core Module (org.springframework.core)
73
74
The core module provides fundamental utilities, I/O abstractions, and type resolution.
75
76
#### Type Resolution and Metadata
77
78
```java { .api }
79
// Encapsulates Java Type information with generic support
80
public class ResolvableType {
81
public static ResolvableType forClass(Class<?> clazz);
82
public static ResolvableType forInstance(Object instance);
83
public ResolvableType[] getGenerics();
84
public Class<?> getRawClass();
85
public ResolvableType getSuperType();
86
public ResolvableType[] getInterfaces();
87
}
88
89
// Helper for resolving method parameters and return types
90
public class MethodParameter {
91
public MethodParameter(Method method, int parameterIndex);
92
public MethodParameter(Constructor<?> constructor, int parameterIndex);
93
public Class<?> getParameterType();
94
public Type getGenericParameterType();
95
public String getParameterName();
96
public ResolvableType getResolvableType();
97
}
98
```
99
100
#### Application Startup Metrics (Spring 5.3+)
101
102
```java { .api }
103
// Interface for instrumenting application startup phases
104
public interface ApplicationStartup {
105
ApplicationStartup DEFAULT = new DefaultApplicationStartup();
106
107
StartupStep start(String name);
108
}
109
110
// Step recording metrics about a particular phase during startup
111
public interface StartupStep {
112
String getName();
113
long getId();
114
StartupStep.Tags getTags();
115
void end();
116
117
// Nested interface for step metadata
118
interface Tags {
119
Tags tag(String key, String value);
120
Tags tag(String key, Supplier<String> value);
121
}
122
}
123
124
// Default no-op implementation
125
public class DefaultApplicationStartup implements ApplicationStartup {
126
@Override
127
public StartupStep start(String name);
128
}
129
130
// Flight Recorder implementation for JFR integration
131
public class FlightRecorderApplicationStartup implements ApplicationStartup {
132
@Override
133
public StartupStep start(String name);
134
}
135
```
136
137
#### Reactive Type Adapters
138
139
```java { .api }
140
// Registry of adapters to adapt Reactive Streams Publisher to/from various async/reactive types
141
public class ReactiveAdapterRegistry {
142
public static ReactiveAdapterRegistry getSharedInstance();
143
144
public void registerReactiveType(ReactiveTypeDescriptor descriptor,
145
Function<Object, Publisher<?>> toAdapter,
146
Function<Publisher<?>, Object> fromAdapter);
147
148
@Nullable
149
public ReactiveAdapter getAdapter(Class<?> reactiveType);
150
@Nullable
151
public ReactiveAdapter getAdapter(@Nullable Class<?> reactiveType, @Nullable Object source);
152
}
153
154
// Adapter for converting between Reactive Streams Publisher and async/reactive types
155
public class ReactiveAdapter {
156
public ReactiveTypeDescriptor getDescriptor();
157
public Publisher<?> toPublisher(Object source);
158
public Object fromPublisher(Publisher<?> publisher);
159
}
160
161
// Descriptor for reactive types (Mono, Flux, Observable, etc.)
162
public class ReactiveTypeDescriptor {
163
public static ReactiveTypeDescriptor singleOptionalValue(Class<?> type, Supplier<Object> emptySupplier);
164
public static ReactiveTypeDescriptor multiValue(Class<?> type, Supplier<Object> emptySupplier);
165
public static ReactiveTypeDescriptor noValue(Class<?> type, Supplier<Object> emptySupplier);
166
167
public Class<?> getReactiveType();
168
public boolean isMultiValue();
169
public boolean isNoValue();
170
public boolean supportsEmpty();
171
}
172
```
173
174
#### Resource Abstraction
175
176
```java { .api }
177
// Interface for abstracting access to low-level resources
178
public interface Resource extends InputStreamSource {
179
boolean exists();
180
boolean isReadable();
181
boolean isOpen();
182
URL getURL() throws IOException;
183
URI getURI() throws IOException;
184
File getFile() throws IOException;
185
long contentLength() throws IOException;
186
long lastModified() throws IOException;
187
String getFilename();
188
String getDescription();
189
}
190
191
// Strategy interface for loading resources
192
public interface ResourceLoader {
193
String CLASSPATH_URL_PREFIX = "classpath:";
194
Resource getResource(String location);
195
ClassLoader getClassLoader();
196
}
197
198
// Common Resource implementations
199
public class ClassPathResource implements Resource {
200
public ClassPathResource(String path);
201
public ClassPathResource(String path, Class<?> clazz);
202
public ClassPathResource(String path, ClassLoader classLoader);
203
}
204
205
public class FileSystemResource implements Resource {
206
public FileSystemResource(String path);
207
public FileSystemResource(File file);
208
public FileSystemResource(Path path);
209
}
210
211
public class UrlResource extends AbstractResource {
212
public UrlResource(URL url);
213
public UrlResource(String protocol, String location);
214
}
215
```
216
217
#### Environment and Property Resolution
218
219
```java { .api }
220
// Interface representing the environment with profiles and properties
221
public interface Environment extends PropertyResolver {
222
String[] getActiveProfiles();
223
String[] getDefaultProfiles();
224
boolean acceptsProfiles(String... profiles);
225
boolean acceptsProfiles(Profiles profiles);
226
}
227
228
// Interface for resolving properties against any underlying source
229
public interface PropertyResolver {
230
boolean containsProperty(String key);
231
String getProperty(String key);
232
String getProperty(String key, String defaultValue);
233
<T> T getProperty(String key, Class<T> targetType);
234
<T> T getProperty(String key, Class<T> targetType, T defaultValue);
235
String resolvePlaceholders(String text);
236
String resolveRequiredPlaceholders(String text) throws IllegalArgumentException;
237
}
238
239
// Abstract base class representing a source of name/value property pairs
240
public abstract class PropertySource<T> {
241
public PropertySource(String name, T source);
242
public String getName();
243
public T getSource();
244
public abstract Object getProperty(String name);
245
}
246
```
247
248
### Spring Beans Module (org.springframework.beans)
249
250
The beans module provides the IoC container implementation and bean lifecycle management.
251
252
#### Bean Factory Interfaces
253
254
```java { .api }
255
// Root interface for accessing Spring bean container
256
public interface BeanFactory {
257
String FACTORY_BEAN_PREFIX = "&";
258
259
Object getBean(String name) throws BeansException;
260
<T> T getBean(String name, Class<T> requiredType) throws BeansException;
261
Object getBean(String name, Object... args) throws BeansException;
262
<T> T getBean(Class<T> requiredType) throws BeansException;
263
<T> T getBean(Class<T> requiredType, Object... args) throws BeansException;
264
265
boolean containsBean(String name);
266
boolean isSingleton(String name) throws NoSuchBeanDefinitionException;
267
boolean isPrototype(String name) throws NoSuchBeanDefinitionException;
268
boolean isTypeMatch(String name, ResolvableType typeToMatch) throws NoSuchBeanDefinitionException;
269
Class<?> getType(String name) throws NoSuchBeanDefinitionException;
270
String[] getAliases(String name);
271
}
272
273
// Extension for factories that can enumerate all beans
274
public interface ListableBeanFactory extends BeanFactory {
275
boolean containsBeanDefinition(String beanName);
276
int getBeanDefinitionCount();
277
String[] getBeanDefinitionNames();
278
String[] getBeanNamesForType(Class<?> type);
279
String[] getBeanNamesForType(ResolvableType type);
280
<T> Map<String, T> getBeansOfType(Class<T> type) throws BeansException;
281
String[] getBeanNamesForAnnotation(Class<? extends Annotation> annotationType);
282
Map<String, Object> getBeansWithAnnotation(Class<? extends Annotation> annotationType) throws BeansException;
283
<A extends Annotation> A findAnnotationOnBean(String beanName, Class<A> annotationType) throws NoSuchBeanDefinitionException;
284
}
285
286
// Configuration interface for most bean factories
287
public interface ConfigurableBeanFactory extends HierarchicalBeanFactory, SingletonBeanRegistry {
288
String SCOPE_SINGLETON = "singleton";
289
String SCOPE_PROTOTYPE = "prototype";
290
291
void setParentBeanFactory(BeanFactory parentBeanFactory) throws IllegalStateException;
292
void setBeanClassLoader(ClassLoader beanClassLoader);
293
ClassLoader getBeanClassLoader();
294
void addBeanPostProcessor(BeanPostProcessor beanPostProcessor);
295
int getBeanPostProcessorCount();
296
void registerScope(String scopeName, Scope scope);
297
String[] getRegisteredScopeNames();
298
Scope getRegisteredScope(String scopeName);
299
}
300
```
301
302
#### Bean Definitions
303
304
```java { .api }
305
// Describes a bean instance with property values and constructor arguments
306
public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement {
307
String SCOPE_SINGLETON = ConfigurableBeanFactory.SCOPE_SINGLETON;
308
String SCOPE_PROTOTYPE = ConfigurableBeanFactory.SCOPE_PROTOTYPE;
309
310
String getBeanClassName();
311
void setBeanClassName(String beanClassName);
312
String getScope();
313
void setScope(String scope);
314
boolean isLazyInit();
315
void setLazyInit(boolean lazyInit);
316
String[] getDependsOn();
317
void setDependsOn(String... dependsOn);
318
boolean isAutowireCandidate();
319
void setAutowireCandidate(boolean autowireCandidate);
320
String getInitMethodName();
321
void setInitMethodName(String initMethodName);
322
String getDestroyMethodName();
323
void setDestroyMethodName(String destroyMethodName);
324
325
ConstructorArgumentValues getConstructorArgumentValues();
326
MutablePropertyValues getPropertyValues();
327
}
328
329
// Holder for BeanDefinition with name and aliases
330
public class BeanDefinitionHolder implements BeanMetadataElement {
331
public BeanDefinitionHolder(BeanDefinition beanDefinition, String beanName);
332
public BeanDefinitionHolder(BeanDefinition beanDefinition, String beanName, String[] aliases);
333
334
public BeanDefinition getBeanDefinition();
335
public String getBeanName();
336
public String[] getAliases();
337
}
338
```
339
340
#### Bean Post Processing
341
342
```java { .api }
343
// Factory hook for custom modification of new bean instances
344
public interface BeanPostProcessor {
345
default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
346
return bean;
347
}
348
349
default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
350
return bean;
351
}
352
}
353
354
// Subinterface that adds before-instantiation callback
355
public interface InstantiationAwareBeanPostProcessor extends BeanPostProcessor {
356
default Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
357
return null;
358
}
359
360
default boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
361
return true;
362
}
363
364
default PropertyValues postProcessPropertyValues(PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException {
365
return pvs;
366
}
367
}
368
369
// Factory hook for custom modification of application context's bean definitions
370
public interface BeanFactoryPostProcessor {
371
void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;
372
}
373
```
374
375
#### Dependency Injection Annotations
376
377
```java { .api }
378
// Marks constructor, field, or method as to be autowired
379
@Target({ElementType.CONSTRUCTOR, ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD, ElementType.ANNOTATION_TYPE})
380
@Retention(RetentionPolicy.RUNTIME)
381
@Documented
382
public @interface Autowired {
383
boolean required() default true;
384
}
385
386
// Qualifier annotation for specifying which bean to inject
387
@Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.TYPE, ElementType.ANNOTATION_TYPE})
388
@Retention(RetentionPolicy.RUNTIME)
389
@Inherited
390
@Documented
391
public @interface Qualifier {
392
String value() default "";
393
}
394
395
// Indicates default value expression for field or parameter
396
@Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.ANNOTATION_TYPE})
397
@Retention(RetentionPolicy.RUNTIME)
398
@Documented
399
public @interface Value {
400
String value();
401
}
402
```
403
404
### Spring Context Module (org.springframework.context)
405
406
The context module provides the ApplicationContext and additional enterprise services.
407
408
#### Application Context
409
410
```java { .api }
411
// Central interface providing configuration for an application
412
public interface ApplicationContext extends EnvironmentCapable, ListableBeanFactory, HierarchicalBeanFactory,
413
MessageSource, ApplicationEventPublisher, ResourcePatternResolver {
414
415
String getId();
416
String getApplicationName();
417
String getDisplayName();
418
long getStartupDate();
419
ApplicationContext getParent();
420
AutowireCapableBeanFactory getAutowireCapableBeanFactory() throws IllegalStateException;
421
}
422
423
// Configuration interface for most application contexts
424
public interface ConfigurableApplicationContext extends ApplicationContext, Lifecycle, Closeable {
425
String CONFIG_LOCATION_DELIMITERS = ",; \t\n";
426
String CONVERSION_SERVICE_BEAN_NAME = "conversionService";
427
String LOAD_TIME_WEAVER_BEAN_NAME = "loadTimeWeaver";
428
String ENVIRONMENT_BEAN_NAME = "environment";
429
String SYSTEM_PROPERTIES_BEAN_NAME = "systemProperties";
430
String SYSTEM_ENVIRONMENT_BEAN_NAME = "systemEnvironment";
431
432
void setId(String id);
433
void setParent(ApplicationContext parent);
434
void setEnvironment(ConfigurableEnvironment environment);
435
ConfigurableEnvironment getEnvironment();
436
void addBeanFactoryPostProcessor(BeanFactoryPostProcessor postProcessor);
437
void addApplicationListener(ApplicationListener<?> listener);
438
void refresh() throws BeansException, IllegalStateException;
439
void registerShutdownHook();
440
void close();
441
boolean isActive();
442
ConfigurableListableBeanFactory getBeanFactory() throws IllegalStateException;
443
}
444
445
// Standalone application context accepting annotated classes as input
446
public class AnnotationConfigApplicationContext extends GenericApplicationContext implements AnnotationConfigRegistry {
447
public AnnotationConfigApplicationContext();
448
public AnnotationConfigApplicationContext(DefaultListableBeanFactory beanFactory);
449
public AnnotationConfigApplicationContext(Class<?>... annotatedClasses);
450
public AnnotationConfigApplicationContext(String... basePackages);
451
452
public void register(Class<?>... annotatedClasses);
453
public void scan(String... basePackages);
454
}
455
```
456
457
#### Configuration Annotations
458
459
```java { .api }
460
// Indicates that a class declares one or more @Bean methods
461
@Target(ElementType.TYPE)
462
@Retention(RetentionPolicy.RUNTIME)
463
@Documented
464
@Component
465
public @interface Configuration {
466
@AliasFor(annotation = Component.class)
467
String value() default "";
468
469
boolean proxyBeanMethods() default true;
470
}
471
472
// Indicates that a method produces a bean to be managed by Spring container
473
@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE})
474
@Retention(RetentionPolicy.RUNTIME)
475
@Documented
476
public @interface Bean {
477
@AliasFor("name")
478
String[] value() default {};
479
480
String[] name() default {};
481
Autowire autowire() default Autowire.NO;
482
boolean autowireCandidate() default true;
483
String initMethod() default "";
484
String destroyMethod() default AbstractBeanDefinition.INFER_METHOD;
485
}
486
487
// Configures component scanning directives
488
@Target(ElementType.TYPE)
489
@Retention(RetentionPolicy.RUNTIME)
490
@Documented
491
@Repeatable(ComponentScans.class)
492
public @interface ComponentScan {
493
@AliasFor("basePackages")
494
String[] value() default {};
495
496
String[] basePackages() default {};
497
Class<?>[] basePackageClasses() default {};
498
Class<? extends BeanNameGenerator> nameGenerator() default BeanNameGenerator.class;
499
Class<? extends ScopeMetadataResolver> scopeResolver() default AnnotationScopeMetadataResolver.class;
500
ScopedProxyMode scopedProxy() default ScopedProxyMode.DEFAULT;
501
String resourcePattern() default ClassPathScanningCandidateComponentProvider.DEFAULT_RESOURCE_PATTERN;
502
boolean useDefaultFilters() default true;
503
Filter[] includeFilters() default {};
504
Filter[] excludeFilters() default {};
505
boolean lazyInit() default false;
506
}
507
```
508
509
#### Component Stereotypes
510
511
```java { .api }
512
// Indicates that an annotated class is a "component"
513
@Target(ElementType.TYPE)
514
@Retention(RetentionPolicy.RUNTIME)
515
@Documented
516
@Indexed
517
public @interface Component {
518
String value() default "";
519
}
520
521
// Indicates that an annotated class is a "Service"
522
@Target(ElementType.TYPE)
523
@Retention(RetentionPolicy.RUNTIME)
524
@Documented
525
@Component
526
public @interface Service {
527
@AliasFor(annotation = Component.class)
528
String value() default "";
529
}
530
531
// Indicates that an annotated class is a "Repository"
532
@Target(ElementType.TYPE)
533
@Retention(RetentionPolicy.RUNTIME)
534
@Documented
535
@Component
536
public @interface Repository {
537
@AliasFor(annotation = Component.class)
538
String value() default "";
539
}
540
```
541
542
#### Event System
543
544
```java { .api }
545
// Class to be extended by all application events
546
public abstract class ApplicationEvent extends EventObject {
547
public ApplicationEvent(Object source);
548
public final long getTimestamp();
549
}
550
551
// Interface to be implemented by application event listeners
552
@FunctionalInterface
553
public interface ApplicationListener<E extends ApplicationEvent> extends EventListener {
554
void onApplicationEvent(E event);
555
}
556
557
// Interface that encapsulates event publication functionality
558
@FunctionalInterface
559
public interface ApplicationEventPublisher {
560
default void publishEvent(ApplicationEvent event) {
561
publishEvent((Object) event);
562
}
563
564
void publishEvent(Object event);
565
}
566
567
// Annotation-based event listener
568
@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE})
569
@Retention(RetentionPolicy.RUNTIME)
570
@Documented
571
public @interface EventListener {
572
@AliasFor("classes")
573
Class<?>[] value() default {};
574
575
Class<?>[] classes() default {};
576
String condition() default "";
577
}
578
```
579
580
## Practical Usage Examples
581
582
### Basic IoC Container Setup
583
584
```java { .api }
585
// Java configuration approach
586
@Configuration
587
@ComponentScan(basePackages = "com.example")
588
public class AppConfig {
589
590
@Bean
591
public DataSource dataSource() {
592
BasicDataSource ds = new BasicDataSource();
593
ds.setDriverClassName("org.h2.Driver");
594
ds.setUrl("jdbc:h2:mem:testdb");
595
return ds;
596
}
597
598
@Bean
599
public PlatformTransactionManager transactionManager(DataSource dataSource) {
600
return new DataSourceTransactionManager(dataSource);
601
}
602
}
603
604
// Application startup
605
public class Application {
606
public static void main(String[] args) {
607
ApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class);
608
609
// Retrieve beans
610
UserService userService = ctx.getBean(UserService.class);
611
DataSource dataSource = ctx.getBean(DataSource.class);
612
613
// Use the beans
614
User user = userService.findById(1L);
615
616
// Clean shutdown
617
((ConfigurableApplicationContext) ctx).close();
618
}
619
}
620
```
621
622
### Dependency Injection Patterns
623
624
```java { .api }
625
// Constructor injection (recommended)
626
@Service
627
public class UserService {
628
629
private final UserRepository userRepository;
630
private final EmailService emailService;
631
632
// @Autowired optional on single constructor
633
public UserService(UserRepository userRepository, EmailService emailService) {
634
this.userRepository = userRepository;
635
this.emailService = emailService;
636
}
637
638
public User createUser(User user) {
639
User saved = userRepository.save(user);
640
emailService.sendWelcomeEmail(saved);
641
return saved;
642
}
643
}
644
645
// Field injection with qualifiers
646
@Component
647
public class NotificationManager {
648
649
@Autowired
650
@Qualifier("emailNotifier")
651
private Notifier emailNotifier;
652
653
@Autowired
654
@Qualifier("smsNotifier")
655
private Notifier smsNotifier;
656
657
public void sendNotification(String message, NotificationType type) {
658
switch (type) {
659
case EMAIL:
660
emailNotifier.send(message);
661
break;
662
case SMS:
663
smsNotifier.send(message);
664
break;
665
}
666
}
667
}
668
669
// Multiple implementations with qualifiers
670
@Component
671
@Qualifier("emailNotifier")
672
public class EmailNotifier implements Notifier {
673
public void send(String message) {
674
// Send email
675
}
676
}
677
678
@Component
679
@Qualifier("smsNotifier")
680
public class SmsNotifier implements Notifier {
681
public void send(String message) {
682
// Send SMS
683
}
684
}
685
```
686
687
### Property Management
688
689
```java { .api }
690
// Property source configuration
691
@Configuration
692
@PropertySource("classpath:application.properties")
693
@PropertySource("classpath:database.properties")
694
public class PropertyConfig {
695
696
@Autowired
697
private Environment env;
698
699
@Bean
700
public DatabaseConfig databaseConfig() {
701
DatabaseConfig config = new DatabaseConfig();
702
config.setUrl(env.getProperty("db.url"));
703
config.setUsername(env.getProperty("db.username"));
704
config.setPassword(env.getProperty("db.password"));
705
config.setMaxConnections(env.getProperty("db.maxConnections", Integer.class, 10));
706
return config;
707
}
708
}
709
710
// Value injection in components
711
@Component
712
public class EmailService {
713
714
@Value("${email.smtp.host}")
715
private String smtpHost;
716
717
@Value("${email.smtp.port:587}")
718
private int smtpPort;
719
720
@Value("${email.from}")
721
private String fromAddress;
722
723
public void sendEmail(String to, String subject, String body) {
724
// Use injected properties
725
}
726
}
727
```
728
729
### Profile-Based Configuration
730
731
```java { .api }
732
// Environment-specific beans
733
@Configuration
734
public class ProfileConfig {
735
736
@Bean
737
@Profile("development")
738
public DataSource devDataSource() {
739
return new EmbeddedDatabaseBuilder()
740
.setType(EmbeddedDatabaseType.H2)
741
.addScript("classpath:schema.sql")
742
.addScript("classpath:test-data.sql")
743
.build();
744
}
745
746
@Bean
747
@Profile("production")
748
public DataSource prodDataSource() {
749
HikariDataSource dataSource = new HikariDataSource();
750
dataSource.setJdbcUrl("jdbc:postgresql://prod-db:5432/myapp");
751
dataSource.setUsername("produser");
752
dataSource.setPassword("prodpass");
753
dataSource.setMaximumPoolSize(20);
754
return dataSource;
755
}
756
757
@Bean
758
@Profile({"development", "test"})
759
public MailSender mockMailSender() {
760
return new MockMailSender();
761
}
762
763
@Bean
764
@Profile("production")
765
public MailSender realMailSender() {
766
JavaMailSenderImpl mailSender = new JavaMailSenderImpl();
767
mailSender.setHost("smtp.company.com");
768
return mailSender;
769
}
770
}
771
```
772
773
### Bean Lifecycle Management
774
775
```java { .api }
776
// Lifecycle interfaces
777
@Component
778
public class DatabaseConnectionManager implements InitializingBean, DisposableBean {
779
780
private Connection connection;
781
782
@Override
783
public void afterPropertiesSet() throws Exception {
784
// Initialize connection after properties are set
785
this.connection = DriverManager.getConnection("jdbc:h2:mem:testdb");
786
System.out.println("Database connection established");
787
}
788
789
@Override
790
public void destroy() throws Exception {
791
// Clean up resources
792
if (connection != null && !connection.isClosed()) {
793
connection.close();
794
System.out.println("Database connection closed");
795
}
796
}
797
}
798
799
// Annotation-based lifecycle
800
@Component
801
public class CacheManager {
802
803
private Map<String, Object> cache;
804
805
@PostConstruct
806
public void initializeCache() {
807
this.cache = new ConcurrentHashMap<>();
808
loadInitialData();
809
System.out.println("Cache initialized");
810
}
811
812
@PreDestroy
813
public void clearCache() {
814
if (cache != null) {
815
cache.clear();
816
System.out.println("Cache cleared");
817
}
818
}
819
820
private void loadInitialData() {
821
// Load initial cache data
822
}
823
}
824
825
// Bean method lifecycle configuration
826
@Configuration
827
public class ServiceConfig {
828
829
@Bean(initMethod = "start", destroyMethod = "stop")
830
public NetworkService networkService() {
831
return new NetworkService();
832
}
833
}
834
```
835
836
### Custom Scopes and Factory Beans
837
838
```java { .api }
839
// Custom FactoryBean
840
@Component
841
public class ConnectionFactoryBean implements FactoryBean<Connection> {
842
843
@Value("${db.url}")
844
private String url;
845
846
@Value("${db.username}")
847
private String username;
848
849
@Value("${db.password}")
850
private String password;
851
852
@Override
853
public Connection getObject() throws Exception {
854
return DriverManager.getConnection(url, username, password);
855
}
856
857
@Override
858
public Class<?> getObjectType() {
859
return Connection.class;
860
}
861
862
@Override
863
public boolean isSingleton() {
864
return false; // New connection each time
865
}
866
}
867
868
// Custom scope (thread scope example)
869
public class ThreadScope implements Scope {
870
871
private final ThreadLocal<Map<String, Object>> threadLocal = new ThreadLocal<Map<String, Object>>() {
872
@Override
873
protected Map<String, Object> initialValue() {
874
return new HashMap<>();
875
}
876
};
877
878
@Override
879
public Object get(String name, ObjectFactory<?> objectFactory) {
880
Map<String, Object> scope = threadLocal.get();
881
Object obj = scope.get(name);
882
if (obj == null) {
883
obj = objectFactory.getObject();
884
scope.put(name, obj);
885
}
886
return obj;
887
}
888
889
@Override
890
public Object remove(String name) {
891
return threadLocal.get().remove(name);
892
}
893
894
@Override
895
public void registerDestructionCallback(String name, Runnable callback) {
896
// Implementation depends on requirements
897
}
898
899
@Override
900
public Object resolveContextualObject(String key) {
901
return null;
902
}
903
904
@Override
905
public String getConversationId() {
906
return Thread.currentThread().getName();
907
}
908
}
909
910
// Register custom scope
911
@Configuration
912
public class ScopeConfig implements BeanFactoryPostProcessor {
913
914
@Override
915
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
916
beanFactory.registerScope("thread", new ThreadScope());
917
}
918
}
919
```
920
921
## Error Handling
922
923
### Common Exceptions
924
925
```java { .api }
926
// Bean creation failures
927
try {
928
MyService service = applicationContext.getBean(MyService.class);
929
} catch (NoSuchBeanDefinitionException e) {
930
// Bean not found
931
log.error("Bean not found: " + e.getMessage());
932
} catch (NoUniqueBeanDefinitionException e) {
933
// Multiple beans found when expecting one
934
log.error("Multiple beans found: " + e.getMessage());
935
} catch (BeanCreationException e) {
936
// Bean creation failed
937
log.error("Bean creation failed: " + e.getMessage(), e);
938
} catch (UnsatisfiedDependencyException e) {
939
// Dependency injection failed
940
log.error("Unsatisfied dependency: " + e.getMessage(), e);
941
}
942
943
// ApplicationContext initialization
944
try {
945
ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
946
} catch (BeanDefinitionStoreException e) {
947
// Invalid bean definitions
948
log.error("Invalid bean definition: " + e.getMessage(), e);
949
} catch (ApplicationContextException e) {
950
// Context initialization failed
951
log.error("Context initialization failed: " + e.getMessage(), e);
952
}
953
```
954
955
The Core Container provides the foundation for all Spring applications, offering powerful dependency injection, comprehensive lifecycle management, and flexible configuration options through annotations or Java configuration classes.