How does AspectJProxyFactory differ from ProxyFactory, and when would you reach for it?
answer
- both extend ProxyCreatorSupport
- addAspect(Class/Object) parses @Before/@Around/@Pointcut
- ReflectiveAspectJAdvisorFactory builds advisors
- still proxy-based, not real weaving
- great for aspect unit tests without a context
basics
~10 sProxyFactory works with low-level advices and advisors. AspectJProxyFactory adds a convenience: you can hand it whole @Aspect-annotated classes with addAspect(), and it turns their @Before/@Around/etc. methods into the proxy's advisor chain for you.
solid answer
~30 s`AspectJProxyFactory` is a sibling of `ProxyFactory` (both extend `ProxyCreatorSupport`) specialized for @AspectJ-style aspects. Where `ProxyFactory` takes raw `Advice`/`Advisor` objects, `AspectJProxyFactory` adds `addAspect(Class<?> aspectClass)` and `addAspect(Object aspectInstance)`, which parse the class's `@Before`/`@After`/`@Around`/`@AfterReturning`/`@AfterThrowing` methods and their `@Pointcut` expressions into Spring `Advisor`s using the same `ReflectiveAspectJAdvisorFactory` the container uses. You still call `getProxy()` to obtain the proxy. Reach for it when you have annotation-based aspects but need to build the proxy programmatically — for example in tests that verify an aspect's behavior against a single target, or in library code that wants @AspectJ ergonomics without a full `ApplicationContext` and `@EnableAspectJAutoProxy`.
code
java · 15 lines@Aspect
public class TimingAspect {
@Around("execution(* com.example..*.*(..))")
public Object time(ProceedingJoinPoint pjp) throws Throwable {
long t = System.nanoTime();
try { return pjp.proceed(); }
finally { System.out.println(pjp.getSignature() + ": " + (System.nanoTime()-t)); }
}
}
// Build a proxy from an @Aspect, no ApplicationContext needed
AspectJProxyFactory factory = new AspectJProxyFactory(new GreeterImpl());
factory.addAspect(TimingAspect.class);
Greeter proxy = factory.getProxy();
proxy.hello("Ada"); // TimingAspect's @Around wraps the callgo deeper
Know it lets you add whole @Aspect classes to a programmatic proxy.
Contrast addAspect() with ProxyFactory's raw addAdvice/addAdvisor and state it's still proxy-based.
Explain it reuses ReflectiveAspectJAdvisorFactory and respects aspect ordering, and its main use in aspect unit tests.
Decide between programmatic AspectJProxyFactory and container auto-proxying, and know the boundary vs. real AspectJ weaving (LTW/CTW).
**Relationship.** Both `org.springframework.aop.framework.ProxyFactory` and `org.springframework.aop.aspectj.annotation.AspectJProxyFactory` extend `ProxyCreatorSupport` (→ `AdvisedSupport` → `Advised`). They produce the same kind of proxy and share the JDK-vs-CGLIB selection, `setProxyTargetClass`, `getProxy()`, and `Advised` introspection. **The key addition.** `AspectJProxyFactory` understands **@AspectJ syntax**. Its distinguishing methods: - `addAspect(Object aspectInstance)` — use an already-created aspect object (can hold state). - `addAspect(Class<?> aspectClass)` — instantiate and use a singleton-style aspect. Internally it uses `AspectMetadata` and `ReflectiveAspectJAdvisorFactory` to read the aspect's advice methods (`@Around`, `@Before`, `@After`, `@AfterReturning`, `@AfterThrowing`) and their pointcut expressions (`@Pointcut` / inline expressions), converting each into a Spring `Advisor` (e.g. `InstantiationModelAwarePointcutAdvisor`) and adding them to the chain in the correct precedence. With plain `ProxyFactory` you'd have to construct those advisors yourself. **What it does NOT do.** It is still Spring **proxy-based** AOP, not real AspectJ weaving. Only externally-called, matched methods on the proxied object are advised; self-invocation and field access are not woven. It doesn't process `@DeclareParents` introductions the way full LTW does beyond what Spring supports, and it needs the target's join points to be proxyable (public/overridable). **Typical usage flow.** ```java AspectJProxyFactory factory = new AspectJProxyFactory(targetObject); factory.addAspect(LoggingAspect.class); factory.setProxyTargetClass(true); // optional CGLIB MyService proxy = factory.getProxy(); ``` **When to use.** - Unit tests that assert an @Aspect's effect on one target without booting a context. - Libraries/tools that want @AspectJ authoring ergonomics but must create proxies by hand. - Ad-hoc wrapping where you already have annotation-based aspects and don't want to translate them into raw `MethodInterceptor`s. **When NOT to.** In a normal Spring application, prefer `@EnableAspectJAutoProxy` (or Spring Boot's auto-config) and let `AnnotationAwareAspectJAutoProxyCreator` apply your `@Aspect @Component` beans to matching beans automatically — you rarely instantiate `AspectJProxyFactory` yourself. **Gotchas.** (1) The result is still a proxy: cast to interface unless `proxyTargetClass=true`. (2) Aspect ordering follows `@Order`/`Ordered` and `@Aspect` precedence rules, same as the container. (3) A stateful aspect passed as an instance is shared across all calls — mind thread-safety. (4) It won't advise calls the target makes on itself.
- Does AspectJProxyFactory perform true AspectJ bytecode weaving?No. It is still Spring proxy-based AOP — it merely parses @AspectJ annotations into Spring advisors on a proxy. Only proxied, externally-invoked join points are advised; there's no field interception or self-invocation weaving. True weaving requires the AspectJ compiler or load-time weaving.
saying these in an interview costs you the question
- Saying AspectJProxyFactory does compile/load-time weaving
- Thinking it can advise self-invocations or field access
- Confusing addAspect() with addAdvice()