skip to content

Compare the weaving models: runtime proxy weaving vs AspectJ compile-time weaving vs AspectJ load-time weaving. How do you enable each?

level: seniorimportance: should knowfreq 40%

answer

  1. Runtime proxy = Spring AOP, no build change
  2. CTW = ajc inlines at compile, zero runtime cost
  3. LTW = agent transforms at class load
  4. LTW needs spring-instrument + @EnableLoadTimeWeaving + aop.xml
  5. Later weaving = richer reach, more setup

basics

~20 s

Spring AOP weaves at runtime by creating a proxy per bean (no build change). AspectJ compile-time weaving uses the ajc compiler to rewrite bytecode when you build. AspectJ load-time weaving rewrites bytecode as classes load, using a javaagent. Later weaving = richer reach but more setup.

solid answer

~50 s

There are three weaving models. **Runtime proxy weaving (Spring AOP)**: at startup an auto-proxy BeanPostProcessor wraps each advised bean in a JDK/CGLIB proxy — no build step, but only bean method executions, and per-call proxy indirection. **AspectJ compile-time weaving (CTW)**: the AspectJ compiler `ajc` (or the AspectJ Maven/Gradle plugin) inlines advice into `.class` bytecode during the build; fastest at runtime, full join-point model, but needs a special compile and access to source/binaries. **AspectJ load-time weaving (LTW)**: a weaving agent transforms bytecode as each class is loaded by the JVM; you enable it with the `spring-instrument` javaagent (`-javaagent:spring-instrument.jar`), `@EnableLoadTimeWeaving`, and a `META-INF/aop.xml`. LTW gives AspectJ's full power without recompiling sources, at the cost of class-load overhead and JVM setup. Rule of thumb: proxy for simplicity, LTW when you need AspectJ reach without a special compiler, CTW when startup/runtime performance is paramount.

code

java · 19 lines
java
// AspectJ LOAD-TIME WEAVING with Spring
// 1) JVM launch flag:  -javaagent:/path/to/spring-instrument-<ver>.jar

@Configuration
@EnableLoadTimeWeaving           // turns on the Spring LoadTimeWeaver
public class WeavingConfig { }

// 2) META-INF/aop.xml on the classpath:
// <aspectj>
//   <weaver options="-Xset:weaveJavaxPackages=false">
//     <include within="com.acme..*"/>
//   </weaver>
//   <aspects>
//     <aspect name="com.acme.aspect.AuditAspect"/>
//   </aspects>
// </aspectj>

// The AuditAspect is a normal @Aspect class, but now it can advise
// field sets, constructors, and non-Spring objects — not just bean methods.

go deeper

for a junior

Knows Spring AOP = runtime proxy, no build step; may not know CTW/LTW names.

for a middle

Distinguishes the three models and that AspectJ needs a compiler or agent.

for a senior

Can enable LTW end-to-end (agent + @EnableLoadTimeWeaving + aop.xml) and reason about per-model overhead.

for a principal

Weighs deployment realities (javaagent availability, build pipeline, startup cost) when standardizing a weaving strategy.

## The spectrum: *when* does advice get connected to code? ### 1. Runtime proxy weaving — Spring AOP **When:** application startup, in memory. **How:** the `AnnotationAwareAspectJAutoProxyCreator` `BeanPostProcessor` (activated by `@EnableAspectJAutoProxy`, automatic in Spring Boot) inspects each bean, and if a pointcut matches, replaces it with a **proxy** — JDK dynamic (interface) or CGLIB (subclass). **Enable:** nothing to do in Spring Boot; add `@Aspect @Component` classes. **Pros:** zero build/JVM changes; pure Java; easy to reason about. **Cons:** bean method executions only; self-invocation gap; small per-call indirection; can't touch fields/constructors/final/static/non-beans. ### 2. AspectJ compile-time weaving (CTW) **When:** at build time. **How:** the AspectJ compiler **`ajc`** (via the `aspectj-maven-plugin` / a Gradle equivalent) compiles your sources *and* the aspects together, **inlining** advice bytecode directly into the target `.class` files. A variant, **binary/post-compile weaving**, weaves already-compiled jars. **Enable:** replace/augment `javac` with `ajc` through the plugin; declare aspects on the `aspectpath`/`inpath`. **Pros:** full AspectJ join-point model; **no runtime weaving cost** and no proxy indirection — the advice is already baked in; can weave code you build. **Cons:** special compiler in the build; slower builds; source/binary access required; harder to toggle. ### 3. AspectJ load-time weaving (LTW) **When:** as each class is loaded by the classloader, before it is used. **How:** a JVM **weaving agent** hooks classloading and transforms bytecode on the fly. In Spring you use the **`spring-instrument`** agent: start the JVM with `-javaagent:/path/spring-instrument.jar`, add **`@EnableLoadTimeWeaving`** (or `<context:load-time-weaver/>`), and provide a **`META-INF/aop.xml`** listing aspects and weave scope. **Enable:** javaagent + `@EnableLoadTimeWeaving` + `aop.xml`. **Pros:** full AspectJ power **without recompiling sources**; scope controlled by `aop.xml`; can weave third-party classes. **Cons:** needs the javaagent (JVM launch flag) — awkward in some PaaS; per-class-load overhead; another config file; harder to debug. ## Same annotations, different engines All three can use the `@Aspect` annotation style. What differs is the **engine**: proxy composition vs. `ajc` bytecode inlining vs. agent-driven load-time transform. Do not assume `@Aspect` implies AspectJ weaving — under Spring AOP it is still a proxy. ## Choosing - **Default:** Spring AOP proxy — covers transactions, security, logging on services. - **Need AspectJ reach but can't/won't change the compiler:** LTW via `spring-instrument` + `@EnableLoadTimeWeaving`. - **Performance-critical, want advice baked in, control the build:** CTW with `ajc`. ## Gotchas - LTW's `-javaagent` must be on the *actual* JVM launch (containers, `JAVA_TOOL_OPTIONS`), which surprises people on Railway/Heroku-style platforms. - CTW and Spring AOP can coexist accidentally and double-weave an aspect if you're not careful. - Proxy weaving's cost is per invocation; CTW's is zero at runtime; LTW's is paid once per class load.

  • What three things must you configure to make Spring drive AspectJ load-time weaving?
    The spring-instrument javaagent on the JVM (-javaagent), @EnableLoadTimeWeaving (or <context:load-time-weaver/>), and a META-INF/aop.xml declaring the aspects and weave scope.
  • Which model has the lowest runtime overhead and why?
    Compile-time weaving — advice is inlined into the target bytecode at build time, so there is no proxy indirection and nothing to weave at runtime.

saying these in an interview costs you the question

  • Saying LTW works without a javaagent
  • Thinking @EnableLoadTimeWeaving alone (no agent, no aop.xml) enables AspectJ
  • Claiming Spring AOP proxying happens at compile time
  • Confusing CTW (ajc, build time) with LTW (agent, class-load time)

context