So far we've looked at explicitly creating an AOP proxy using a ProxyFactoryBean
or similar factory
bean.
Spring also allows us to use "auto-proxy" bean definitions, which can automatically proxy selected bean definitions. This principle is built on Spring's "bean postprocessor" infrastructure, which allows any bean definition to be modified as the container loads.
In this model, you set some specific bean definitions in your XML bean definition file to configure the auto-proxy
infrastructure. This allows you to declare targets that are suitable for auto-proxying. There is no need to use
ProxyFactoryBean
.
You can do this in two ways:
-
Using an auto-proxy creator that references specific beans in the current context.
-
A special case of auto-proxy creation that deserves special consideration: creating an auto-proxy based on source-level metadata attributes.
Bean definitions with auto-proxy
This section covers the auto proxy creators provided by the org.springframework.aop.framework.autoproxy
package.
BeanNameAutoProxyCreator
The class BeanNameAutoProxyCreator
is a BeanPostProcessor
that automatically creates AOP
proxies for beans with names that match literal values or wildcards. The following example shows how to create a
bean BeanNameAutoProxyCreator
:
<bean class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
<property name="beanNames" value="jdk*,onlyJdk"/>
<property name="interceptorNames">
<list>
<value>myInterceptor</value>
</list>
</property>
</bean>
As in ProxyFactoryBean
, there is a interceptorNames
property here, rather than a list of
interceptors, to ensure the correct logic of the prototype advisors. Named "interceptors" can be advisors or advice
of any type.
As with autoproxy in general, the main point of using the BeanNameAutoProxyCreator
is to consistently
apply the same configuration to multiple objects with minimal configuration. This is a popular way to apply
declarative transactions to multiple objects.
Bean definitions that have the same name, such as jdkMyBean
and onlyJdk
in the previous
example, are normal bean definitions with a target class. The AOP proxy is automatically created using BeanNameAutoProxyCreator
.
The same advice applies to all relevant beans. Note that if advisors are used (rather than the interceptor in the
previous example), slices can be applied differently to different beans.
DefaultAdvisorAutoProxyCreator
A more common but extremely effective auto proxy creator is DefaultAdvisorAutoProxyCreator
. It
automatically applies the appropriate EAs in the current context, without the need to include specific bean names in
the auto-proxy EA bean definition. It offers the same benefits of consistent configuration and duplication avoidance
as BeanNameAutoProxyCreator
.
Uses of this mechanism include:
-
Setting the bean definition
DefaultAdvisorAutoProxyCreator
. -
Assigning any number of advisors in the same or adjacent contexts. Please note that these must be advisors and not interceptors or other advisories. This is necessary because a computed slice must exist to check that each tip matches the definitions of the candidate bins.
DefaultAdvisorAutoProxyCreator
automatically calculates the slice contained in each advisor to know
which advice (if any) it should apply to each business object (for example, businessObject1
and businessObject2
in the example).
This means that any number of advisors can be automatically applied to each business object. If none of the advisors match any method of the business object, the object will not be proxied. As bean definitions are added for new business objects, they are automatically proxied if necessary.
The advantage of autoproxy in general is that it prevents calling code or dependencies from obtaining an object that
is not provided with advice. Calling getBean("businessObject1")
on this ApplicationContext
returns the AOP proxy, not the target business object. (The "inner bin" approach shown earlier also provides this
benefit.)
The following example creates the DefaultAdvisorAutoProxyCreator
bean and the other elements discussed
in this section:
<bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"/>
<bean class="org.springframework.transaction.interceptor.TransactionAttributeSourceAdvisor">
<property name="transactionInterceptor" ref="transactionInterceptor"/>
</bean>
<bean id="customAdvisor" class="com.mycompany.MyAdvisor"/>
<bean id="businessObject1" class="com.mycompany.BusinessObject1">
<!-- Properties omitted -->
</bean>
<bean id="businessObject2" class="com.mycompany.BusinessObject2"/>
DefaultAdvisorAutoProxyCreator
is very useful if you need to consistently apply the same advice to many
business objects. Once infrastructure definitions are created, new business objects can be added without enabling a
specific proxy configuration. You can also easily add additional aspects (such as tracing or performance monitoring
aspects) with minimal configuration changes.
DefaultAdvisorAutoProxyCreator
offers support for filtering (by using a naming convention so that only
specific advisors are evaluated, allowing multiple differently configured AdvisorAutoProxyCreators to be used in the
same factory) and ordering. Advisors can implement the org.springframework.core.Ordered
interface to
ensure proper ordering if this is an issue. The TransactionAttributeSourceAdvisor
used in the previous
example has a custom ordering value. The default is "unordered".