1
0
Files
spring-boot-demo/spring-aop/docs/01-what-spring-aop-is.md
Ankur Mhatre 86246dc860 Three new article modules: configuration binding, profiles and config data, Spring AOP
configuration-properties/  @ConfigurationProperties vs @Value on Spring Boot 4.1.1.
  The relaxed-binding matrix is generated by binding each spelling rather than
  transcribed, and re-checked against real processes -- the in-process probe was
  wrong twice before it was right. Records the three findings that came out of it:
  @Value does get relaxed resolution inside Spring Boot (Boot attaches
  ConfigurationPropertySources), the configuration processor silently stops
  generating metadata on JDK 23+ when declared as a plain dependency, and @Valid is
  not what makes nested constraints run.

profiles-and-config/       Precedence, profiles, spring.config.import and config trees.
  /precedence reports every source holding a property in rank order with file and
  line, which turns "my profile file had no effect" into a two-line answer. Also
  pins the counterintuitive one: an imported file outranks the file that imported it.

spring-aop/                Designators, proxy types, and aspects that do not fire.
  One advice per supported designator so the reference table is generated from real
  matches; all fourteen unsupported designators fed to the parser. Two corrections to
  the reference documentation: unsupported designators throw
  UnsupportedPointcutPrimitiveException (extends RuntimeException, not
  IllegalArgumentException), and spring-boot-starter-aop was renamed to
  spring-boot-starter-aspectj in Boot 4.

19 contract tests across the three modules, 15 captured transcripts, all regenerated
by scripts/run-all.sh. Verified on Spring Boot 4.1.1, Spring Framework 7.0.9,
JDK 25.0.4.1.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Gip4srpzMwjgoba6uEfbr5
2026-09-08 16:47:48 +00:00

2.3 KiB

Index · Designators →

1. What Spring AOP actually is

Spring AOP is a proxy mechanism that borrows AspectJ's pointcut language. Both halves of that sentence explain a failure mode.

It is proxies

Spring does not modify your bytecode. When a bean matches a pointcut, the container puts a proxy in the bean registry in its place. Callers get the proxy; the proxy runs advice and then forwards to the real object.

Everything that follows from this:

  • Only beans can be advised. An object created with new has no proxy.
  • Only calls through the proxy are intercepted. A call the object makes to itself is not.
  • Only overridable methods can be advised: not private, not final, not static.
  • Join points are method executions. Field access, constructor calls and exception handlers are not available, no matter what the pointcut language allows you to write.

It borrows the pointcut language

aspectjweaver on the classpath supplies the pointcut parser. Spring uses it to decide which methods match and then does its own weaving with proxies. AspectJ's own weaver is not involved.

This is why the designator list is a subset: the language can express call() and cflow(), and a proxy cannot implement them. See chapter 2.

The Spring Boot 4 starter rename

In Spring Boot 3 the dependency was spring-boot-starter-aop. In Spring Boot 4 it is spring-boot-starter-aspectj.

spring-boot-starter-aop      last published 4.0.0-M2   (last GA: 3.5.16)
spring-boot-starter-aspectj  first published 4.0.0-M3

The contents are unchanged: spring-boot-starter, spring-aop, aspectjweaver. But the old artifact is no longer in the Boot BOM, so copying a dependency block out of any pre-4 tutorial fails resolution with a missing-version error rather than a helpful message.

Without the starter, @Aspect classes are ordinary beans, no pointcut is ever parsed, and every aspect in the application silently matches nothing.

When to use something else

If you need to advise field access, constructors, or calls between objects you do not own, you need real AspectJ weaving (compile-time or load-time), not Spring AOP. If you need to advise one internal call, you need to refactor — see chapter 5.