skip to content

Walk through everything required to enable Spring Load-Time Weaving: the annotation, aop.xml, and the Java agent. What does each piece do?

level: middleimportance: must knowfreq 40%

answer

  1. 3 legs: annotation + aop.xml + agent
  2. @EnableLoadTimeWeaving → InstrumentationLoadTimeWeaver
  3. aop.xml = <aspects> + <weaver><include>
  4. -javaagent:spring-instrument or aspectjweaver
  5. no agent = silently no weaving

basics

~10 s

Add @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 s

Three 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
xml
<!-- 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

for a junior

Recognize the three pieces by name even if fuzzy on details.

for a middle

Explain what each of the three pieces contributes and the classic no-agent failure.

for a senior

Discuss AUTODETECT, container-provided weavers, include-filter performance, and load-ordering pitfalls.

for a principal

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/

context