Backend Development 11 min read

Mastering Spring ProxyFactoryBean: A Complete Guide to AOP Proxy Configuration

This article explains how to use Spring's ProxyFactoryBean to create AOP proxies, covering its properties, the choice between JDK and CGLIB proxies, bean configuration examples, global advisors, and practical considerations for proxying classes versus interfaces.

Spring Full-Stack Practical Cases
Spring Full-Stack Practical Cases
Spring Full-Stack Practical Cases
Mastering Spring ProxyFactoryBean: A Complete Guide to AOP Proxy Configuration

Environment

Spring 5.3.25

Overview

The basic way to create an AOP proxy in Spring is to use org.springframework.aop.framework.ProxyFactoryBean , which gives full control over pointcuts, advices, and their order. Simpler alternatives exist when such fine‑grained control is not required.

Like other Spring FactoryBean implementations, ProxyFactoryBean introduces an indirection layer: referencing a bean named foo that is a ProxyFactoryBean returns the object created by its getObject() method, i.e., the AOP proxy that wraps the target.

One major benefit of using ProxyFactoryBean (or any IoC‑managed class) to create AOP proxies is that the IoC container also manages the Advice and Pointcut, enabling dependency injection for advices—a powerful feature that is hard to achieve with other AOP frameworks.

ProxyFactoryBean Properties

target : the object to be proxied.

proxyTargetClass : if true , forces the creation of a CGLIB proxy even when interfaces are present.

optimize : applies aggressive optimizations to CGLIB proxies; has no effect on JDK dynamic proxies.

frozen : when true , prevents further changes to the proxy configuration after creation.

exposeProxy : if true , exposes the current proxy via ThreadLocal so that the target can obtain it via AopContext.currentProxy() .

proxyInterfaces : an array of interface names; if omitted, the target class’s interfaces are used.

interceptorNames : an array of bean names for advisors, interceptors, or other advice objects; a trailing * acts as a wildcard for global advisors.

singleton : determines whether getObject() always returns the same instance (default true ).

Choosing Between JDK and CGLIB Proxies

If the target class does not implement any interfaces, Spring creates a CGLIB proxy automatically.

If the target class implements one or more interfaces, the proxy type depends on the proxyTargetClass and proxyInterfaces settings:

When proxyTargetClass=true , a CGLIB proxy is created regardless of interfaces.

When proxyInterfaces is set, a JDK proxy implementing the specified interfaces is created.

If proxyInterfaces is not set but the target implements interfaces, Spring automatically creates a JDK proxy for all implemented interfaces.

Example: Defining a Proxy with Advisors

<code>&lt;bean id="personTarget" class="com.mycompany.PersonImpl"&gt;
  &lt;property name="name" value="Tony"/&gt;
  &lt;property name="age" value="51"/&gt;
&lt;/bean&gt;

&lt;bean id="myAdvisor" class="com.mycompany.MyAdvisor"&gt;
  &lt;property name="someProperty" value="Custom string property value"/&gt;
&lt;/bean&gt;

&lt;bean id="debugInterceptor" class="org.springframework.aop.interceptor.DebugInterceptor"/&gt;

&lt;bean id="person" class="org.springframework.aop.framework.ProxyFactoryBean"&gt;
  &lt;property name="proxyInterfaces" value="com.mycompany.Person"/&gt;
  &lt;property name="target" ref="personTarget"/&gt;
  &lt;property name="interceptorNames"&gt;
    &lt;list&gt;
      &lt;value&gt;myAdvisor&lt;/value&gt;
      &lt;value&gt;debugInterceptor&lt;/value&gt;
    &lt;/list&gt;
  &lt;/property&gt;
&lt;/bean&gt;</code>

Retrieving the proxy:

<code>Person person = (Person) factory.getBean("person");</code>

Other beans in the same IoC context can depend on this proxy just like any regular bean:

<code>&lt;bean id="personUser" class="com.mycompany.PersonUser"&gt;
  &lt;property name="person"&gt;&lt;ref bean="person"/&gt;&lt;/property&gt;
&lt;/bean&gt;</code>

Proxying a Class Directly

When the target class has no interfaces, set proxyTargetClass=true to force a CGLIB proxy. This is useful for legacy code that does not follow the interface‑based design, although programming to interfaces is generally recommended.

Note that CGLIB proxies cannot advise final methods because they cannot be overridden.

Final methods are not eligible for advice.

CGLIB is bundled with Spring core since version 3.2, so no additional dependency is required.

Using Global Advisors

Appending a wildcard * to an interceptor name adds all advisors whose bean names match the prefix. Example:

<code>&lt;bean id="proxy" class="org.springframework.aop.framework.ProxyFactoryBean"&gt;
  &lt;property name="target" ref="service"/&gt;
  &lt;property name="interceptorNames"&gt;
    &lt;list&gt;
      &lt;value&gt;global*&lt;/value&gt;
    &lt;/list&gt;
  &lt;/property&gt;
&lt;/bean&gt;

&lt;bean id="global_debug" class="org.springframework.aop.interceptor.DebugInterceptor"/&gt;
&lt;bean id="global_performance" class="org.springframework.aop.interceptor.PerformanceMonitorInterceptor"/&gt;</code>

Conclusion

ProxyFactoryBean provides a flexible way to create AOP proxies in Spring, allowing fine‑grained control over proxy type, advised interfaces, and global advisors.

JavaAOPIoCSpringCglibProxyFactoryBean
Spring Full-Stack Practical Cases
Written by

Spring Full-Stack Practical Cases

Full-stack Java development with Vue 2/3 front-end suite; hands-on examples and source code analysis for Spring, Spring Boot 2/3, and Spring Cloud.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.