0
# Annotation Configuration
1
2
Annotation-driven configuration providing the foundation for modern Java-based Spring configuration. This includes @Configuration classes, @Bean methods, component scanning, import mechanisms, and conditional processing for building Spring applications declaratively.
3
4
## Capabilities
5
6
### Configuration Classes
7
8
Core annotations for defining configuration classes that replace or supplement XML configuration.
9
10
```java { .api }
11
/**
12
* Indicates that a class declares one or more @Bean methods and may be processed
13
* by the Spring container to generate bean definitions and service requests for those beans at runtime.
14
*/
15
@Target(ElementType.TYPE)
16
@Retention(RetentionPolicy.RUNTIME)
17
@Component
18
public @interface Configuration {
19
/**
20
* Explicitly specify the name of the Spring bean definition associated with the @Configuration class.
21
* @return the specified bean name, if any (or empty String otherwise)
22
*/
23
@AliasFor(annotation = Component.class)
24
String value() default "";
25
26
/**
27
* Specify whether @Bean methods should get proxied in order to enforce bean lifecycle behavior.
28
* @return whether to proxy @Bean methods
29
*/
30
boolean proxyBeanMethods() default true;
31
32
/**
33
* Specify whether @Bean methods need to have unique names within this configuration class.
34
* @return whether @Bean methods need unique names
35
*/
36
boolean enforceUniqueMethods() default true;
37
}
38
39
/**
40
* Indicates that a method produces a bean to be managed by the Spring container.
41
*/
42
@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE})
43
@Retention(RetentionPolicy.RUNTIME)
44
public @interface Bean {
45
/**
46
* Alias for name(). Intended to be used when no other attributes are needed.
47
* @return the names for this bean, or an empty array if none
48
*/
49
@AliasFor("name")
50
String[] value() default {};
51
52
/**
53
* The name of this bean, or if several names, a primary bean name plus aliases.
54
* @return the names for this bean, or an empty array if none
55
*/
56
@AliasFor("value")
57
String[] name() default {};
58
59
/**
60
* Are dependencies to be injected via autowiring?
61
* @return the autowire mode for the bean
62
*/
63
Autowire autowire() default Autowire.NO;
64
65
/**
66
* Is this bean a candidate for getting autowired into some other bean?
67
* @return whether the bean is a candidate for autowiring
68
*/
69
boolean autowireCandidate() default true;
70
71
/**
72
* The optional name of a method to call on the bean instance during initialization.
73
* @return the init method name, if any (or empty String otherwise)
74
*/
75
String initMethod() default "";
76
77
/**
78
* The optional name of a method to call on the bean instance upon closing the application context.
79
* @return the destroy method name, if any (or empty String otherwise)
80
*/
81
String destroyMethod() default AbstractBeanDefinition.INFER_METHOD;
82
}
83
```
84
85
### Component Scanning
86
87
Annotations and infrastructure for automatic detection and registration of Spring components.
88
89
```java { .api }
90
/**
91
* Configures component scanning directives for use with @Configuration classes.
92
*/
93
@Target(ElementType.TYPE)
94
@Retention(RetentionPolicy.RUNTIME)
95
@Repeatable(ComponentScans.class)
96
public @interface ComponentScan {
97
/**
98
* Alias for the basePackages() attribute.
99
* @return the base packages to scan
100
*/
101
@AliasFor("basePackages")
102
String[] value() default {};
103
104
/**
105
* Base packages to scan for annotated components.
106
* @return the base packages to scan
107
*/
108
@AliasFor("value")
109
String[] basePackages() default {};
110
111
/**
112
* Type-safe alternative to basePackages() for specifying the packages to scan for annotated components.
113
* @return classes whose packages should be scanned
114
*/
115
Class<?>[] basePackageClasses() default {};
116
117
/**
118
* The BeanNameGenerator class to be used for naming detected components within the Spring container.
119
* @return the BeanNameGenerator class, or DefaultBeanNameGenerator if not specified
120
*/
121
Class<? extends BeanNameGenerator> nameGenerator() default BeanNameGenerator.class;
122
123
/**
124
* The ScopeMetadataResolver to be used for resolving the scope of detected components.
125
* @return the ScopeMetadataResolver class
126
*/
127
Class<? extends ScopeMetadataResolver> scopeResolver() default AnnotationScopeMetadataResolver.class;
128
129
/**
130
* Indicates whether proxies should be generated for detected components.
131
* @return the scoped-proxy mode
132
*/
133
ScopedProxyMode scopedProxy() default ScopedProxyMode.DEFAULT;
134
135
/**
136
* Controls the class files eligible for component detection.
137
* @return the resource pattern for component detection
138
*/
139
String resourcePattern() default ClassPathScanningCandidateComponentProvider.DEFAULT_RESOURCE_PATTERN;
140
141
/**
142
* Indicates whether automatic detection of classes annotated with @Component, @Repository, @Service, or @Controller should be enabled.
143
* @return whether to use default filters
144
*/
145
boolean useDefaultFilters() default true;
146
147
/**
148
* Specifies which types are eligible for component scanning.
149
* @return the include filters
150
*/
151
Filter[] includeFilters() default {};
152
153
/**
154
* Specifies which types are not eligible for component scanning.
155
* @return the exclude filters
156
*/
157
Filter[] excludeFilters() default {};
158
159
/**
160
* Specify whether scanned beans should be registered for lazy initialization.
161
* @return whether to register beans for lazy initialization
162
*/
163
boolean lazyInit() default false;
164
165
/**
166
* Declares the type filter to be used as an include filter or exclude filter.
167
*/
168
@Retention(RetentionPolicy.RUNTIME)
169
@Target({})
170
@interface Filter {
171
/**
172
* The type of filter to use.
173
* @return the filter type
174
*/
175
FilterType type() default FilterType.ANNOTATION;
176
177
/**
178
* Alias for classes().
179
* @return the classes to use for filtering
180
*/
181
@AliasFor("classes")
182
Class<?>[] value() default {};
183
184
/**
185
* The class or classes to use as the filter.
186
* @return the classes to use for filtering
187
*/
188
@AliasFor("value")
189
Class<?>[] classes() default {};
190
191
/**
192
* The pattern (or patterns) to use for the filter, as an alternative to specifying a Class value.
193
* @return the patterns for filtering
194
*/
195
String[] pattern() default {};
196
}
197
}
198
199
/**
200
* Container annotation that aggregates several @ComponentScan annotations.
201
*/
202
@Target(ElementType.TYPE)
203
@Retention(RetentionPolicy.RUNTIME)
204
public @interface ComponentScans {
205
ComponentScan[] value();
206
}
207
208
/**
209
* Enumeration of the type filters that may be used in conjunction with @ComponentScan.
210
*/
211
public enum FilterType {
212
/** Filter candidates marked with a given annotation */
213
ANNOTATION,
214
/** Filter candidates assignable to a given type */
215
ASSIGNABLE_TYPE,
216
/** Filter candidates matching a given AspectJ type pattern expression */
217
ASPECTJ,
218
/** Filter candidates matching a given regex pattern */
219
REGEX,
220
/** Filter candidates using a given custom TypeFilter implementation */
221
CUSTOM
222
}
223
```
224
225
### Import Mechanisms
226
227
Annotations for importing additional configuration classes and resources.
228
229
```java { .api }
230
/**
231
* Indicates one or more component classes to import — typically @Configuration classes.
232
*/
233
@Target(ElementType.TYPE)
234
@Retention(RetentionPolicy.RUNTIME)
235
public @interface Import {
236
/**
237
* Component classes to import.
238
* @return the classes to import
239
*/
240
Class<?>[] value();
241
}
242
243
/**
244
* Indicates one or more resources containing bean definitions to import.
245
*/
246
@Target(ElementType.TYPE)
247
@Retention(RetentionPolicy.RUNTIME)
248
public @interface ImportResource {
249
/**
250
* Alias for locations().
251
* @return the resource locations
252
*/
253
@AliasFor("locations")
254
String[] value() default {};
255
256
/**
257
* Resource locations from which to import.
258
* @return the resource locations
259
*/
260
@AliasFor("value")
261
String[] locations() default {};
262
263
/**
264
* BeanDefinitionReader implementation to use when processing resources specified via the value() attribute.
265
* @return the BeanDefinitionReader class
266
*/
267
Class<? extends BeanDefinitionReader> reader() default BeanDefinitionReader.class;
268
}
269
270
/**
271
* Interface to be implemented by types that determine which @Configuration classes should be imported
272
* based on a given selection criteria.
273
*/
274
public interface ImportSelector {
275
/**
276
* Select and return the names of which class(es) should be imported based on the AnnotationMetadata
277
* of the importing @Configuration class.
278
* @param importingClassMetadata the metadata of the importing class
279
* @return the class names, or an empty array if none
280
*/
281
String[] selectImports(AnnotationMetadata importingClassMetadata);
282
283
/**
284
* Return a predicate for excluding classes from the import candidates.
285
* @return a predicate to apply to candidate class names
286
*/
287
default Predicate<String> getExclusionFilter() {
288
return null;
289
}
290
}
291
292
/**
293
* A variation of ImportSelector that runs after all @Configuration beans have been processed.
294
*/
295
public interface DeferredImportSelector extends ImportSelector {
296
/**
297
* Return a specific import group.
298
* @return the import group class, or null for the default import group
299
*/
300
default Class<? extends Group> getImportGroup() {
301
return null;
302
}
303
304
/**
305
* Interface used to group results from different import selectors.
306
*/
307
interface Group {
308
/**
309
* Process the AnnotationMetadata of the importing @Configuration class using the specified DeferredImportSelector.
310
* @param metadata the metadata of the importing class
311
* @param selector the selector that has been processed
312
*/
313
void process(AnnotationMetadata metadata, DeferredImportSelector selector);
314
315
/**
316
* Return the Entry objects that contain the selections of which class(es) should be imported
317
* for this group.
318
* @return the selections to import
319
*/
320
Iterable<Entry> selectImports();
321
322
/**
323
* An entry that holds the AnnotationMetadata of the importing Configuration class
324
* and the class name to import.
325
*/
326
class Entry {
327
private final AnnotationMetadata metadata;
328
private final String importClassName;
329
330
public Entry(AnnotationMetadata metadata, String importClassName) {}
331
public AnnotationMetadata getMetadata() {}
332
public String getImportClassName() {}
333
}
334
}
335
}
336
337
/**
338
* Interface to be implemented by types that register additional bean definitions when
339
* processing @Configuration classes.
340
*/
341
public interface ImportBeanDefinitionRegistrar {
342
/**
343
* Register bean definitions as necessary based on the given annotation metadata
344
* of the importing @Configuration class.
345
* @param importingClassMetadata annotation metadata of the importing class
346
* @param registry current bean definition registry
347
* @param importBeanNameGenerator the bean name generator
348
*/
349
default void registerBeanDefinitions(AnnotationMetadata importingClassMetadata,
350
BeanDefinitionRegistry registry,
351
BeanNameGenerator importBeanNameGenerator) {}
352
}
353
```
354
355
### Property Sources
356
357
Annotations for adding property sources to the environment.
358
359
```java { .api }
360
/**
361
* Annotation providing a convenient and declarative mechanism for adding a PropertySource to Spring's Environment.
362
*/
363
@Target(ElementType.TYPE)
364
@Retention(RetentionPolicy.RUNTIME)
365
@Repeatable(PropertySources.class)
366
public @interface PropertySource {
367
/**
368
* Indicate the name of this property source.
369
* @return the name of the property source, or empty string if not specified
370
*/
371
String name() default "";
372
373
/**
374
* Indicate the resource location(s) of the properties file to be loaded.
375
* @return the resource locations
376
*/
377
String[] value();
378
379
/**
380
* Indicate if a failure to find a property resource should be ignored.
381
* @return whether to ignore resource not found
382
*/
383
boolean ignoreResourceNotFound() default false;
384
385
/**
386
* A specific character encoding for the given resources, e.g. "UTF-8".
387
* @return the encoding for the resources
388
*/
389
String encoding() default "";
390
391
/**
392
* Specify a custom PropertySourceFactory, if any.
393
* @return the PropertySourceFactory class
394
*/
395
Class<? extends PropertySourceFactory> factory() default PropertySourceFactory.class;
396
}
397
398
/**
399
* Container annotation that aggregates several @PropertySource annotations.
400
*/
401
@Target(ElementType.TYPE)
402
@Retention(RetentionPolicy.RUNTIME)
403
public @interface PropertySources {
404
PropertySource[] value();
405
}
406
```
407
408
### Conditional Processing
409
410
Annotations and interfaces for conditional bean registration and configuration.
411
412
```java { .api }
413
/**
414
* Indicates that a component is only eligible for registration when all specified conditions match.
415
*/
416
@Target({ElementType.TYPE, ElementType.METHOD})
417
@Retention(RetentionPolicy.RUNTIME)
418
public @interface Conditional {
419
/**
420
* All Condition classes that must match in order for the component to be registered.
421
* @return the condition classes
422
*/
423
Class<? extends Condition>[] value();
424
}
425
426
/**
427
* A single condition that must be matched in order for a component to be registered.
428
*/
429
public interface Condition {
430
/**
431
* Determine if the condition matches.
432
* @param context the condition context
433
* @param metadata the metadata of the class or method being checked
434
* @return true if the condition matches and the component can be registered
435
*/
436
boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata);
437
}
438
439
/**
440
* Context information for use by Condition implementations.
441
*/
442
public interface ConditionContext {
443
/**
444
* Return the BeanDefinitionRegistry that will hold the bean definition should this condition match.
445
* @return the bean definition registry
446
*/
447
BeanDefinitionRegistry getRegistry();
448
449
/**
450
* Return the ConfigurableListableBeanFactory that will hold the bean definition should this condition match.
451
* @return the bean factory, or null if not available
452
*/
453
ConfigurableListableBeanFactory getBeanFactory();
454
455
/**
456
* Return the Environment for which the current application is running.
457
* @return the environment
458
*/
459
Environment getEnvironment();
460
461
/**
462
* Return the ResourceLoader currently being used.
463
* @return the resource loader
464
*/
465
ResourceLoader getResourceLoader();
466
467
/**
468
* Return the ClassLoader that should be used to load additional classes.
469
* @return the class loader, or null if the default ClassLoader should be used
470
*/
471
ClassLoader getClassLoader();
472
}
473
474
/**
475
* Indicate that a component is eligible for registration when one or more specified profiles are active.
476
*/
477
@Target({ElementType.TYPE, ElementType.METHOD})
478
@Retention(RetentionPolicy.RUNTIME)
479
@Conditional(ProfileCondition.class)
480
public @interface Profile {
481
/**
482
* The set of profiles for which the annotated component should be registered.
483
* @return the applicable profiles
484
*/
485
String[] value();
486
}
487
```
488
489
### Scoping and Lifecycle Annotations
490
491
Annotations for controlling bean scope and lifecycle behavior.
492
493
```java { .api }
494
/**
495
* When used as a type-level annotation in conjunction with @Component, @Scope indicates the name of a scope to use
496
* for instances of the annotated type.
497
*/
498
@Target({ElementType.TYPE, ElementType.METHOD})
499
@Retention(RetentionPolicy.RUNTIME)
500
public @interface Scope {
501
/**
502
* Alias for scopeName().
503
* @return the scope name
504
*/
505
@AliasFor("scopeName")
506
String value() default "";
507
508
/**
509
* Specifies the name of the scope to use for the annotated component/bean.
510
* @return the scope name
511
*/
512
@AliasFor("value")
513
String scopeName() default "";
514
515
/**
516
* Specifies whether a component should be configured as a scoped proxy and if so, whether the proxy should be interface-based or subclass-based.
517
* @return the scoped proxy mode
518
*/
519
ScopedProxyMode proxyMode() default ScopedProxyMode.DEFAULT;
520
}
521
522
/**
523
* Enumerates the various scoped-proxy options.
524
*/
525
public enum ScopedProxyMode {
526
/** Default typically equals NO, unless a different default has been configured at the component-scan instruction level */
527
DEFAULT,
528
/** Do not create a scoped proxy */
529
NO,
530
/** Create a JDK dynamic proxy implementing all interfaces exposed by the target object's class */
531
INTERFACES,
532
/** Create a class-based proxy (uses CGLIB) */
533
TARGET_CLASS
534
}
535
536
/**
537
* Indicates whether a bean should be lazily initialized.
538
*/
539
@Target({ElementType.TYPE, ElementType.METHOD, ElementType.CONSTRUCTOR, ElementType.PARAMETER, ElementType.FIELD})
540
@Retention(RetentionPolicy.RUNTIME)
541
public @interface Lazy {
542
/**
543
* Whether lazy initialization should occur.
544
* @return whether to apply lazy initialization
545
*/
546
boolean value() default true;
547
}
548
549
/**
550
* Beans on which the current bean depends.
551
*/
552
@Target({ElementType.TYPE, ElementType.METHOD})
553
@Retention(RetentionPolicy.RUNTIME)
554
public @interface DependsOn {
555
/**
556
* The names of the beans that the current bean depends on.
557
* @return the names of dependent beans
558
*/
559
String[] value() default {};
560
}
561
562
/**
563
* Indicates that a bean should be given preference when multiple candidates are qualified to autowire a single-valued dependency.
564
*/
565
@Target({ElementType.TYPE, ElementType.METHOD})
566
@Retention(RetentionPolicy.RUNTIME)
567
public @interface Primary {
568
}
569
570
/**
571
* Indicates that a bean should be considered as a fallback when no other matching candidates exist.
572
*/
573
@Target({ElementType.TYPE, ElementType.METHOD})
574
@Retention(RetentionPolicy.RUNTIME)
575
public @interface Fallback {
576
}
577
```
578
579
### Bean Name Generation and Scope Resolution
580
581
Infrastructure classes for customizing bean naming and scope resolution.
582
583
```java { .api }
584
/**
585
* BeanNameGenerator implementation for bean classes annotated with the @Component annotation
586
* or with another annotation that is itself annotated with @Component as a meta-annotation.
587
*/
588
public class AnnotationBeanNameGenerator implements BeanNameGenerator {
589
/**
590
* Generate a bean name for the given bean definition.
591
* @param definition the bean definition to generate a name for
592
* @param registry the bean definition registry
593
* @return the generated bean name
594
*/
595
public String generateBeanName(BeanDefinition definition, BeanDefinitionRegistry registry) {}
596
}
597
598
/**
599
* An extension of AnnotationBeanNameGenerator that uses the fully qualified class name
600
* as the default bean name if an explicit bean name is not specified.
601
*/
602
public class FullyQualifiedAnnotationBeanNameGenerator extends AnnotationBeanNameGenerator {
603
/**
604
* Generate a bean name for the given bean definition.
605
* @param definition the bean definition to generate a name for
606
* @param registry the bean definition registry
607
* @return the generated bean name
608
*/
609
public String generateBeanName(BeanDefinition definition, BeanDefinitionRegistry registry) {}
610
}
611
612
/**
613
* Strategy interface for resolving the scope of bean definitions.
614
*/
615
public interface ScopeMetadataResolver {
616
/**
617
* Resolve the ScopeMetadata appropriate to the supplied bean definition.
618
* @param definition the target bean definition
619
* @return the relevant ScopeMetadata
620
*/
621
ScopeMetadata resolveScopeMetadata(BeanDefinition definition);
622
}
623
624
/**
625
* A ScopeMetadataResolver implementation that by default checks for the presence of Spring's @Scope annotation
626
* on the bean class.
627
*/
628
public class AnnotationScopeMetadataResolver implements ScopeMetadataResolver {
629
/**
630
* Resolve the ScopeMetadata appropriate to the supplied bean definition.
631
* @param definition the target bean definition
632
* @return the relevant ScopeMetadata
633
*/
634
public ScopeMetadata resolveScopeMetadata(BeanDefinition definition) {}
635
}
636
637
/**
638
* Encapsulates scope characteristics for a Spring-managed bean including the scope name and the scoped-proxy behavior.
639
*/
640
public class ScopeMetadata {
641
/**
642
* Get the name of the scope.
643
* @return the scope name
644
*/
645
public String getScopeName() {}
646
647
/**
648
* Set the name of the scope.
649
* @param scopeName the scope name
650
*/
651
public void setScopeName(String scopeName) {}
652
653
/**
654
* Get the proxy mode for scoped instances.
655
* @return the scoped proxy mode
656
*/
657
public ScopedProxyMode getScopedProxyMode() {}
658
659
/**
660
* Set the proxy mode for scoped instances.
661
* @param scopedProxyMode the scoped proxy mode
662
*/
663
public void setScopedProxyMode(ScopedProxyMode scopedProxyMode) {}
664
}
665
```
666
667
### Usage Examples
668
669
**Basic Configuration Class:**
670
671
```java
672
import org.springframework.context.annotation.Configuration;
673
import org.springframework.context.annotation.Bean;
674
import org.springframework.context.annotation.ComponentScan;
675
676
@Configuration
677
@ComponentScan(basePackages = "com.example")
678
public class AppConfig {
679
680
@Bean
681
public UserService userService() {
682
return new UserService(userRepository());
683
}
684
685
@Bean
686
public UserRepository userRepository() {
687
return new JpaUserRepository();
688
}
689
690
@Bean
691
@Primary
692
public DataSource primaryDataSource() {
693
// Configure primary data source
694
return new HikariDataSource();
695
}
696
697
@Bean("backupDataSource")
698
@Lazy
699
public DataSource backupDataSource() {
700
// Configure backup data source
701
return new HikariDataSource();
702
}
703
}
704
```
705
706
**Component Scanning with Filters:**
707
708
```java
709
@Configuration
710
@ComponentScan(
711
basePackages = "com.example",
712
includeFilters = @ComponentScan.Filter(
713
type = FilterType.ANNOTATION,
714
classes = Service.class
715
),
716
excludeFilters = @ComponentScan.Filter(
717
type = FilterType.REGEX,
718
pattern = ".*Test.*"
719
)
720
)
721
public class ScanConfig {
722
}
723
```
724
725
**Conditional Configuration:**
726
727
```java
728
@Configuration
729
@Profile("development")
730
public class DevConfig {
731
732
@Bean
733
@Conditional(DatabaseAvailableCondition.class)
734
public DataSource dataSource() {
735
return new H2DataSource();
736
}
737
}
738
739
public class DatabaseAvailableCondition implements Condition {
740
@Override
741
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
742
Environment env = context.getEnvironment();
743
return env.containsProperty("database.url");
744
}
745
}
746
```
747
748
**Import Configuration:**
749
750
```java
751
@Configuration
752
@Import({DatabaseConfig.class, SecurityConfig.class})
753
@ImportResource("classpath:legacy-config.xml")
754
@PropertySource("classpath:application.properties")
755
public class MainConfig {
756
}
757
758
@Configuration
759
public class DatabaseConfig {
760
@Bean
761
public DataSource dataSource() {
762
return new HikariDataSource();
763
}
764
}
765
```