skip to content

Load-Time Weaving (LTW)

Load-time weaving instruments classes as they are loaded, via a Java agent and META-INF/aop.xml, with no proxy involved. It comes up when a scenario needs advice on objects Spring did not create.

part ofSpring Frameworkoverview, primer and where to startread it →
on this pageshow

questions

5

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

open as a page

What is Load-Time Weaving (LTW) in Spring AOP, and how does it differ from Spring's default proxy-based AOP?

level: juniorimportance: should knowfreq 35%

basics

~10 s

Load-Time Weaving inserts aspect code into class bytecode as the JVM loads each class, using a Java agent. Spring's default AOP instead wraps beans in runtime proxy objects and only advises Spring-managed beans.

open as a page

Explain the underlying mechanism of Spring LTW: how does @EnableLoadTimeWeaving actually get bytecode transformed at class-load time?

level: seniorimportance: should knowfreq 30%

basics

~20 s

The Java agent captures the JVM's Instrumentation handle. Spring's InstrumentationLoadTimeWeaver registers an AspectJ ClassFileTransformer through it. As each class loads, the JVM passes its bytes to that transformer, which weaves in matching advice before the class is defined.

open as a page

When would you choose Load-Time Weaving over Spring's proxy-based AOP, and what are the costs of that choice?

level: seniorimportance: should knowfreq 45%

basics

~10 s

Choose LTW when proxies can't reach the join point: self-invocations, private/final methods, non-Spring objects, or objects created with new (e.g. @Configurable). Costs are a required Java agent, slower startup, and classloader/deployment complexity.

open as a page

You're introducing Spring LTW into a production, containerized Spring Boot service. What operational risks and gotchas would you flag, and how do you de-risk the rollout?

level: principalimportance: nice to knowfreq 18%

basics

~20 s

Main risks: the agent must be present in every environment (image, CI, local) or aspects silently vanish; startup slows from class scanning; classloader/ordering issues; and AspectJ semantics differ from Spring AOP. De-risk by baking the agent into the image, scoping aop.xml tightly, and verifying with -showWeaveInfo.

open as a page