Walk through everything required to enable Spring Load-Time Weaving: the annotation, aop.xml, and the Java agent. What does each piece do?
answer
- 3 legs: annotation + aop.xml + agent
- @EnableLoadTimeWeaving → InstrumentationLoadTimeWeaver
- aop.xml = <aspects> + <weaver><include>
- -javaagent:spring-instrument or aspectjweaver
- no agent = silently no weaving
basics
~10 sAdd @EnableLoadTimeWeaving on a config class, provide META-INF/aop.xml naming the aspects and packages to weave, and start the JVM with a java agent (-javaagent:spring-instrument.jar or aspectjweaver.jar) so classes can be transformed as they load.
solid answer
~40 sThree pieces work together. First, @EnableLoadTimeWeaving (or <context:load-time-weaver/>) registers a LoadTimeWeaver bean and hooks Spring into the JVM's instrumentation. Second, META-INF/aop.xml is the AspectJ weaver's config: an <aspects> section listing the aspect classes and an <weaver> section with <include> filters limiting which packages get scanned (crucial for startup performance). Third, an agent must be present so a ClassFileTransformer can actually rewrite bytecode before each class is defined: -javaagent:spring-instrument-<ver>.jar (Spring's lightweight agent) or -javaagent:aspectjweaver.jar (full AspectJ). Some servlet containers register a weaver automatically, letting @EnableLoadTimeWeaving(aspectjWeaving = AUTODETECT) enable it only when aop.xml is found. Without the agent, no transformer can run and nothing is woven.
code
xml · 15 lines<!-- src/main/resources/META-INF/aop.xml -->
<aspectj>
<aspects>
<!-- @Aspect annotation-style aspect to weave -->
<aspect name="com.example.audit.AuditAspect"/>
</aspects>
<weaver options="-showWeaveInfo">
<!-- Restrict weaving scope; keeps startup fast -->
<include within="com.example..*"/>
</weaver>
</aspectj>
<!-- Launch:
java -javaagent:/libs/spring-instrument-6.1.0.jar -jar app.jar -->go deeper
Recognize the three pieces by name even if fuzzy on details.
Explain what each of the three pieces contributes and the classic no-agent failure.
Discuss AUTODETECT, container-provided weavers, include-filter performance, and load-ordering pitfalls.
Own the launch/packaging story (agent distribution, container vs fat-jar), and gate LTW adoption on real need.
LTW in Spring is a three-legged stool — remove any leg and it silently does nothing or fails at startup. ## 1. `@EnableLoadTimeWeaving` (Spring side) Put it on a `@Configuration` class (XML equivalent: `<context:load-time-weaver/>`). It: - Registers a **`LoadTimeWeaver`** bean (named `loadTimeWeaver`). The concrete type is usually **`InstrumentationLoadTimeWeaver`**, which wraps the JVM's `java.lang.instrument.Instrumentation`. - Wires the AspectJ weaving `ClassFileTransformer` into that weaver so matching classes get transformed as they load. It has an attribute **`aspectjWeaving`** with values `ENABLED`, `DISABLED`, and `AUTODETECT` (the default). `AUTODETECT` turns weaving on only if a `META-INF/aop.xml` is found on the classpath. You can also implement **`LoadTimeWeavingConfigurer`** to supply a custom `LoadTimeWeaver` (e.g. for a specific app server). ## 2. `META-INF/aop.xml` (AspectJ side) This is **not** a Spring file — it is AspectJ's own weaver configuration, discovered on the classpath. It has two key sections: ```xml <aspectj> <aspects> <aspect name="com.example.audit.AuditAspect"/> </aspects> <weaver options="-verbose -showWeaveInfo"> <include within="com.example..*"/> </weaver> </aspectj> ``` - `<aspects>` lists the aspect classes to apply (they must be on the classpath; annotation-style `@Aspect` classes are supported). - `<weaver>` controls scope and diagnostics. The **`<include within=...>`** filters are important: without them the weaver inspects *every* class the JVM loads, which slows startup badly. `options` like `-showWeaveInfo` / `-verbose` print what got woven — invaluable when "nothing is happening." You can have multiple `aop.xml` files (one per jar); AspectJ merges them. ## 3. The Java agent (JVM side) A `ClassFileTransformer` can only be installed if the JVM was started with an **agent** that grabs the `Instrumentation` handle. Two common choices: - **`-javaagent:spring-instrument-<version>.jar`** — Spring's minimal agent (`InstrumentationSavingAgent`). It just captures `Instrumentation` so Spring's `InstrumentationLoadTimeWeaver` can use it. Lightweight; used together with `@EnableLoadTimeWeaving`. - **`-javaagent:aspectjweaver-<version>.jar`** — the full AspectJ agent. It reads `aop.xml` and weaves directly, independent of Spring's plumbing. Some environments differ: - Certain **application servers / servlet containers** expose an instrumentable classloader, so Spring can weave **without** a `-javaagent` flag (this is why `AUTODETECT` exists). Plain `java -jar` (e.g. a Boot fat jar) does **not** — you must pass the agent. - The agent must be an actual file path on the launch command; it cannot be added purely from application code after the JVM has started. ## Putting it together / common failure modes - **No agent** → `InstrumentationLoadTimeWeaver` has no `Instrumentation` → weaving is skipped (or Spring throws that instrumentation is unavailable). This is the #1 "my aspect never runs" cause. - **aop.xml missing or in the wrong place** (must be `META-INF/aop.xml`) → nothing to weave. - **No `<include>`** → works but huge startup penalty as every class is scanned. - **Class already loaded before the weaver is ready** → a class loaded during early bootstrap won't be woven; ordering matters. Use `-verbose` to spot "already defined" warnings. ## When to use Only when you need weaving proxies can't provide (self-invocation, non-bean classes, `@Configurable` domain objects). Otherwise the agent + aop.xml overhead isn't worth it.
- You added @EnableLoadTimeWeaving and aop.xml but the aspect never fires from a plain `java -jar app.jar`. Why?No agent is attached, so no Instrumentation handle exists and no ClassFileTransformer can rewrite bytecode. You must launch with -javaagent:spring-instrument.jar (or aspectjweaver.jar). A plain fat-jar run does not provide an instrumentable classloader by itself.
- What is the practical purpose of the <include within=...> element in aop.xml?It limits which classes the weaver examines. Without it, AspectJ inspects every class the JVM loads, adding significant startup latency; restricting to your own packages keeps weaving fast and avoids accidentally weaving library/JDK classes.
saying these in an interview costs you the question
- Claiming @EnableLoadTimeWeaving alone is enough, no agent needed
- Thinking aop.xml is a Spring-specific file rather than AspectJ's config
- Believing a Boot fat jar auto-provides an instrumentation agent
- Putting aop.xml somewhere other than META-INF/