or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

annotation-configuration.mdapplication-context.mdcaching.mdconfiguration-properties.mddependency-injection.mdevent-handling.mdformatting.mdindex.mdlifecycle-management.mdscheduling.mdvalidation.md

annotation-configuration.mddocs/

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

```