or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

annotation-processing.mdaot-optimization.mdcore-infrastructure.mdenvironment-config.mdindex.mdresource-management.mdtask-execution.mdtype-conversion.mdutilities.md

annotation-processing.mddocs/

0

# Annotation Processing

1

2

Spring Core provides comprehensive annotation processing capabilities that enable meta-annotation support, attribute overrides, and sophisticated annotation composition. This system forms the foundation for Spring's annotation-driven programming model.

3

4

## Core Annotation Support

5

6

Spring provides several key annotations and utilities for annotation processing.

7

8

**Core Annotations**

9

```java { .api }

10

@Target({ElementType.TYPE, ElementType.METHOD, ElementType.FIELD})

11

@Retention(RetentionPolicy.RUNTIME)

12

@Documented

13

public @interface Order {

14

int value() default Ordered.LOWEST_PRECEDENCE;

15

}

16

17

@Target(ElementType.METHOD)

18

@Retention(RetentionPolicy.RUNTIME)

19

@Documented

20

public @interface AliasFor {

21

String value() default "";

22

String attribute() default "";

23

Class<? extends Annotation> annotation() default Annotation.class;

24

}

25

```

26

27

**Usage Examples**

28

```java

29

// Using @Order annotation

30

@Component

31

@Order(1)

32

public class HighPriorityService {

33

// Implementation

34

}

35

36

@Component

37

@Order(Ordered.HIGHEST_PRECEDENCE)

38

public class CriticalService {

39

// Implementation

40

}

41

42

// Using @AliasFor for attribute aliasing

43

@Target(ElementType.TYPE)

44

@Retention(RetentionPolicy.RUNTIME)

45

@Component

46

public @interface Service {

47

@AliasFor(annotation = Component.class)

48

String value() default "";

49

50

@AliasFor("value")

51

String name() default "";

52

}

53

54

@Service("userService") // Equivalent to @Service(name = "userService")

55

public class UserService {

56

// Implementation

57

}

58

```

59

60

## Merged Annotations System

61

62

Spring's merged annotation system provides a powerful way to handle annotation composition, inheritance, and attribute overrides.

63

64

**MergedAnnotations Interface**

65

```java { .api }

66

public interface MergedAnnotations extends Iterable<MergedAnnotation<Annotation>> {

67

<A extends Annotation> boolean isPresent(Class<A> annotationType);

68

boolean isPresent(String annotationType);

69

70

<A extends Annotation> boolean isDirectlyPresent(Class<A> annotationType);

71

boolean isDirectlyPresent(String annotationType);

72

73

<A extends Annotation> MergedAnnotation<A> get(Class<A> annotationType);

74

<A extends Annotation> MergedAnnotation<A> get(Class<A> annotationType,

75

Predicate<? super MergedAnnotation<A>> predicate);

76

MergedAnnotation<Annotation> get(String annotationType);

77

MergedAnnotation<Annotation> get(String annotationType,

78

Predicate<? super MergedAnnotation<Annotation>> predicate);

79

80

<A extends Annotation> Stream<MergedAnnotation<A>> stream(Class<A> annotationType);

81

Stream<MergedAnnotation<Annotation>> stream(String annotationType);

82

Stream<MergedAnnotation<Annotation>> stream();

83

84

// Static factory methods

85

static MergedAnnotations from(AnnotatedElement element);

86

static MergedAnnotations from(AnnotatedElement element, SearchStrategy searchStrategy);

87

static MergedAnnotations from(Annotation... annotations);

88

static MergedAnnotations from(Object source, Annotation... annotations);

89

}

90

91

public enum SearchStrategy {

92

DIRECT,

93

INHERITED_ANNOTATIONS,

94

SUPERCLASS,

95

TYPE_HIERARCHY,

96

TYPE_HIERARCHY_AND_ENCLOSING_CLASSES

97

}

98

```

99

100

**MergedAnnotation Interface**

101

```java { .api }

102

public interface MergedAnnotation<A extends Annotation> {

103

Class<A> getType();

104

boolean isPresent();

105

boolean isDirectlyPresent();

106

boolean isMetaPresent();

107

108

int getDistance();

109

int getAggregateIndex();

110

Object getSource();

111

MergedAnnotation<?> getParent();

112

MergedAnnotation<A> getRoot();

113

114

List<Class<? extends Annotation>> getMetaTypes();

115

116

boolean hasAttribute(String attributeName);

117

boolean hasDefaultValue(String attributeName);

118

119

<T> Optional<T> getValue(String attributeName);

120

<T> Optional<T> getValue(String attributeName, Class<T> type);

121

<T> Optional<T> getDefaultValue(String attributeName);

122

<T> Optional<T> getDefaultValue(String attributeName, Class<T> type);

123

124

MergedAnnotation<A> filterAttributes(Predicate<String> predicate);

125

MergedAnnotation<A> withAttribute(String attributeName, Object value);

126

127

AnnotationAttributes asAnnotationAttributes();

128

AnnotationAttributes asAnnotationAttributes(Adapt... adaptations);

129

Map<String, Object> asMap();

130

Map<String, Object> asMap(Adapt... adaptations);

131

132

<T extends Map<String, Object>> T asMap(Function<MergedAnnotation<?>, T> factory, Adapt... adaptations);

133

134

A synthesize();

135

A synthesize(Predicate<String> condition) throws NoSuchElementException;

136

137

Optional<A> synthesize(Predicate<String> condition);

138

139

enum Adapt {

140

CLASS_TO_STRING,

141

ANNOTATION_TO_MAP

142

}

143

}

144

```

145

146

**Usage Examples**

147

```java

148

// Basic merged annotation usage

149

@Service

150

@Transactional

151

public class BusinessService {

152

public void processData() { }

153

}

154

155

Class<?> serviceClass = BusinessService.class;

156

MergedAnnotations annotations = MergedAnnotations.from(serviceClass);

157

158

// Check for annotation presence

159

boolean hasService = annotations.isPresent(Service.class);

160

boolean hasTransactional = annotations.isPresent(Transactional.class);

161

boolean hasComponent = annotations.isPresent(Component.class); // true due to @Service -> @Component

162

163

// Get merged annotation with attribute values

164

MergedAnnotation<Service> serviceAnnotation = annotations.get(Service.class);

165

String serviceName = serviceAnnotation.getValue("value", String.class).orElse("");

166

167

// Work with meta-annotations

168

MergedAnnotation<Component> componentAnnotation = annotations.get(Component.class);

169

boolean isMetaPresent = componentAnnotation.isMetaPresent(); // true

170

int distance = componentAnnotation.getDistance(); // 1 (via @Service)

171

172

// Stream all annotations

173

annotations.stream()

174

.forEach(annotation -> {

175

System.out.println("Found: " + annotation.getType().getSimpleName());

176

System.out.println("Distance: " + annotation.getDistance());

177

});

178

179

// Get annotation attributes

180

Method method = BusinessService.class.getMethod("processData");

181

MergedAnnotations methodAnnotations = MergedAnnotations.from(method);

182

MergedAnnotation<Transactional> txAnnotation = methodAnnotations.get(Transactional.class);

183

184

Map<String, Object> attributes = txAnnotation.asMap();

185

String propagation = txAnnotation.getValue("propagation", String.class).orElse("REQUIRED");

186

```

187

188

## Annotation Utilities

189

190

Spring provides extensive utilities for working with annotations in various contexts.

191

192

**AnnotationUtils Class**

193

```java { .api }

194

public abstract class AnnotationUtils {

195

// Find annotations

196

public static <A extends Annotation> A findAnnotation(Method method, Class<A> annotationType);

197

public static <A extends Annotation> A findAnnotation(Class<?> clazz, Class<A> annotationType);

198

public static <A extends Annotation> A findAnnotation(AnnotatedElement annotatedElement, Class<A> annotationType);

199

200

// Get annotation attributes

201

public static Map<String, Object> getAnnotationAttributes(Annotation annotation);

202

public static Map<String, Object> getAnnotationAttributes(Annotation annotation, boolean classValuesAsString);

203

public static Map<String, Object> getAnnotationAttributes(Annotation annotation, boolean classValuesAsString, boolean nestedAnnotationsAsMap);

204

205

// Synthesize annotations

206

public static <A extends Annotation> A synthesizeAnnotation(A annotation);

207

public static <A extends Annotation> A synthesizeAnnotation(A annotation, AnnotatedElement annotatedElement);

208

public static <A extends Annotation> A synthesizeAnnotation(Map<String, Object> attributes, Class<A> annotationType, AnnotatedElement annotatedElement);

209

210

// Utility methods

211

public static boolean isCandidateClass(Class<?> clazz, Class<? extends Annotation> annotationType);

212

public static boolean isCandidateClass(Class<?> clazz, Collection<Class<? extends Annotation>> annotationTypes);

213

public static boolean isCandidateClass(Class<?> clazz, String annotationName);

214

215

public static String getDefaultValue(Class<? extends Annotation> annotationType, String attributeName);

216

public static <A extends Annotation> A getAnnotation(Annotation annotation, Class<A> annotationType);

217

public static <A extends Annotation> A getAnnotation(AnnotatedElement annotatedElement, Class<A> annotationType);

218

219

public static void clearCache();

220

}

221

```

222

223

**AnnotatedElementUtils Class**

224

```java { .api }

225

public abstract class AnnotatedElementUtils {

226

// Has annotation checks

227

public static boolean hasAnnotation(AnnotatedElement element, Class<? extends Annotation> annotationType);

228

public static boolean hasAnnotation(AnnotatedElement element, String annotationName);

229

230

// Find merged annotations

231

public static <A extends Annotation> A findMergedAnnotation(AnnotatedElement element, Class<A> annotationType);

232

public static <A extends Annotation> A findMergedAnnotation(AnnotatedElement element, String annotationName);

233

234

public static <A extends Annotation> Set<A> findAllMergedAnnotations(AnnotatedElement element, Class<A> annotationType);

235

public static Set<Annotation> findAllMergedAnnotations(AnnotatedElement element, Set<Class<? extends Annotation>> annotationTypes);

236

237

// Get merged annotation attributes

238

public static AnnotationAttributes findMergedAnnotationAttributes(AnnotatedElement element, Class<? extends Annotation> annotationType, boolean classValuesAsString, boolean nestedAnnotationsAsMap);

239

public static AnnotationAttributes findMergedAnnotationAttributes(AnnotatedElement element, String annotationName, boolean classValuesAsString, boolean nestedAnnotationsAsMap);

240

241

public static MultiValueMap<String, Object> getAllAnnotationAttributes(AnnotatedElement element, String annotationName);

242

public static MultiValueMap<String, Object> getAllAnnotationAttributes(AnnotatedElement element, String annotationName, boolean classValuesAsString, boolean nestedAnnotationsAsMap);

243

244

// Meta-annotation support

245

public static boolean isAnnotated(AnnotatedElement element, Class<? extends Annotation> annotationType);

246

public static boolean isAnnotated(AnnotatedElement element, String annotationName);

247

248

public static AnnotationAttributes getMergedAnnotationAttributes(AnnotatedElement element, Class<? extends Annotation> annotationType);

249

public static AnnotationAttributes getMergedAnnotationAttributes(AnnotatedElement element, String annotationName);

250

}

251

```

252

253

**Usage Examples**

254

```java

255

// Define custom annotation with meta-annotation support

256

@Target(ElementType.TYPE)

257

@Retention(RetentionPolicy.RUNTIME)

258

@Service

259

@Transactional(propagation = Propagation.REQUIRED)

260

public @interface BusinessService {

261

@AliasFor(annotation = Service.class, attribute = "value")

262

String value() default "";

263

264

@AliasFor(annotation = Transactional.class, attribute = "timeout")

265

int timeout() default -1;

266

}

267

268

@BusinessService("orderService")

269

public class OrderService {

270

public void processOrder() { }

271

}

272

273

// Use AnnotationUtils

274

Class<?> orderServiceClass = OrderService.class;

275

276

// Find annotations (follows meta-annotation hierarchy)

277

Service serviceAnnotation = AnnotationUtils.findAnnotation(orderServiceClass, Service.class);

278

Transactional txAnnotation = AnnotationUtils.findAnnotation(orderServiceClass, Transactional.class);

279

280

// Get annotation attributes

281

Map<String, Object> businessServiceAttrs = AnnotationUtils.getAnnotationAttributes(

282

orderServiceClass.getAnnotation(BusinessService.class)

283

);

284

285

// Synthesize annotation with attribute overrides

286

BusinessService businessServiceAnn = orderServiceClass.getAnnotation(BusinessService.class);

287

Service synthesizedService = AnnotationUtils.synthesizeAnnotation(businessServiceAnn, orderServiceClass);

288

289

// Use AnnotatedElementUtils for more advanced processing

290

boolean hasService = AnnotatedElementUtils.hasAnnotation(orderServiceClass, Service.class); // true

291

boolean hasTransactional = AnnotatedElementUtils.hasAnnotation(orderServiceClass, Transactional.class); // true

292

293

// Find merged annotations with attribute overrides resolved

294

Service mergedService = AnnotatedElementUtils.findMergedAnnotation(orderServiceClass, Service.class);

295

String serviceName = mergedService.value(); // "orderService"

296

297

Transactional mergedTx = AnnotatedElementUtils.findMergedAnnotation(orderServiceClass, Transactional.class);

298

Propagation propagation = mergedTx.propagation(); // REQUIRED

299

int timeout = mergedTx.timeout(); // resolved from BusinessService.timeout

300

301

// Get merged annotation attributes

302

AnnotationAttributes serviceAttrs = AnnotatedElementUtils.findMergedAnnotationAttributes(

303

orderServiceClass, Service.class, false, false

304

);

305

306

AnnotationAttributes txAttrs = AnnotatedElementUtils.findMergedAnnotationAttributes(

307

orderServiceClass, Transactional.class, false, false

308

);

309

```

310

311

## Annotation Order Comparators

312

313

Spring provides ordering support that respects the `@Order` annotation and `Ordered` interface.

314

315

**AnnotationAwareOrderComparator Class**

316

```java { .api }

317

public class AnnotationAwareOrderComparator extends OrderComparator {

318

public static final AnnotationAwareOrderComparator INSTANCE = new AnnotationAwareOrderComparator();

319

320

public static void sort(List<?> list);

321

public static void sort(Object[] array);

322

323

@Override

324

protected Integer findOrder(Object obj);

325

public Integer getPriority(Object obj);

326

327

protected Integer findOrderFromAnnotation(Object obj);

328

}

329

```

330

331

**Usage Examples**

332

```java

333

// Components with different ordering

334

@Component

335

@Order(1)

336

public class FirstComponent { }

337

338

@Component

339

@Order(3)

340

public class ThirdComponent { }

341

342

@Component

343

public class UnorderedComponent implements Ordered {

344

@Override

345

public int getOrder() {

346

return 2;

347

}

348

}

349

350

// Sort components by order

351

List<Object> components = Arrays.asList(

352

new ThirdComponent(),

353

new FirstComponent(),

354

new UnorderedComponent()

355

);

356

357

AnnotationAwareOrderComparator.sort(components);

358

// Result: [FirstComponent(1), UnorderedComponent(2), ThirdComponent(3)]

359

360

// Check ordering at runtime

361

AnnotationAwareOrderComparator comparator = AnnotationAwareOrderComparator.INSTANCE;

362

Integer firstOrder = comparator.findOrder(new FirstComponent()); // 1

363

Integer thirdOrder = comparator.findOrder(new ThirdComponent()); // 3

364

```

365

366

## Annotation Attributes Support

367

368

**AnnotationAttributes Class**

369

```java { .api }

370

public class AnnotationAttributes extends LinkedHashMap<String, Object> {

371

public AnnotationAttributes();

372

public AnnotationAttributes(Class<? extends Annotation> annotationType);

373

public AnnotationAttributes(Map<String, Object> map);

374

public AnnotationAttributes(AnnotationAttributes other);

375

376

public Class<? extends Annotation> annotationType();

377

public String getDisplayName();

378

379

// Type-safe attribute access

380

public String getString(String attributeName);

381

public String[] getStringArray(String attributeName);

382

public boolean getBoolean(String attributeName);

383

public <N extends Number> N getNumber(String attributeName);

384

public <E extends Enum<?>> E getEnum(String attributeName);

385

public <T> Class<? extends T> getClass(String attributeName);

386

public Class<?>[] getClassArray(String attributeName);

387

public AnnotationAttributes getAnnotation(String attributeName);

388

public <A extends Annotation> A getAnnotation(String attributeName, Class<A> annotationType);

389

public AnnotationAttributes[] getAnnotationArray(String attributeName);

390

391

// Static factory methods

392

public static AnnotationAttributes fromMap(Map<String, Object> map);

393

}

394

```

395

396

**Usage Examples**

397

```java

398

// Create and populate annotation attributes

399

AnnotationAttributes attributes = new AnnotationAttributes(Service.class);

400

attributes.put("value", "myService");

401

attributes.put("qualifiers", new String[]{"primary", "default"});

402

403

// Type-safe access

404

String serviceName = attributes.getString("value"); // "myService"

405

String[] qualifiers = attributes.getStringArray("qualifiers"); // ["primary", "default"]

406

407

// From annotation

408

@Component("testComponent")

409

public class TestComponent { }

410

411

Annotation componentAnn = TestComponent.class.getAnnotation(Component.class);

412

Map<String, Object> attrMap = AnnotationUtils.getAnnotationAttributes(componentAnn);

413

AnnotationAttributes componentAttrs = AnnotationAttributes.fromMap(attrMap);

414

415

String componentName = componentAttrs.getString("value"); // "testComponent"

416

```

417

418

## Annotation Value Resolution

419

420

**AnnotationValueResolver**

421

```java { .api }

422

public interface AnnotationValueResolver {

423

Object resolve(Object value);

424

425

static AnnotationValueResolver none() {

426

return value -> value;

427

}

428

}

429

430

public final class AnnotationConfigUtils {

431

public static final String CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME =

432

"org.springframework.context.annotation.internalConfigurationAnnotationProcessor";

433

434

public static final String AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME =

435

"org.springframework.context.annotation.internalAutowiredAnnotationProcessor";

436

437

public static final String COMMON_ANNOTATION_PROCESSOR_BEAN_NAME =

438

"org.springframework.context.annotation.internalCommonAnnotationProcessor";

439

440

public static final String EVENT_LISTENER_PROCESSOR_BEAN_NAME =

441

"org.springframework.context.event.internalEventListenerProcessor";

442

443

public static final String EVENT_LISTENER_FACTORY_BEAN_NAME =

444

"org.springframework.context.event.internalEventListenerFactory";

445

}

446

```

447

448

## Custom Annotation Processing

449

450

**RepeatableContainers Support**

451

```java { .api }

452

public final class RepeatableContainers {

453

public static RepeatableContainers standardRepeatables();

454

public static RepeatableContainers of(Class<? extends Annotation> container, Class<? extends Annotation> repeatable);

455

public static RepeatableContainers none();

456

457

public RepeatableContainers and(Class<? extends Annotation> container, Class<? extends Annotation> repeatable);

458

459

Annotation[] findRepeatedAnnotations(Annotation annotation);

460

}

461

```

462

463

**Usage Examples**

464

```java

465

// Define repeatable annotation

466

@Target(ElementType.TYPE)

467

@Retention(RetentionPolicy.RUNTIME)

468

@Repeatable(Qualifiers.class)

469

public @interface Qualifier {

470

String value();

471

}

472

473

@Target(ElementType.TYPE)

474

@Retention(RetentionPolicy.RUNTIME)

475

public @interface Qualifiers {

476

Qualifier[] value();

477

}

478

479

// Use repeatable annotations

480

@Qualifier("primary")

481

@Qualifier("default")

482

@Component

483

public class MultiQualifiedComponent { }

484

485

// Process repeatable annotations

486

Class<?> componentClass = MultiQualifiedComponent.class;

487

MergedAnnotations annotations = MergedAnnotations.from(componentClass);

488

489

// Get all instances of repeatable annotation

490

Stream<MergedAnnotation<Qualifier>> qualifiers = annotations.stream(Qualifier.class);

491

List<String> qualifierValues = qualifiers

492

.map(q -> q.getValue("value", String.class).orElse(""))

493

.collect(Collectors.toList());

494

// Result: ["primary", "default"]

495

```

496

497

This comprehensive annotation processing system enables Spring's powerful declarative programming model, allowing developers to use annotations not just as markers but as configuration vehicles with rich attribute processing and composition capabilities.